Index: trunk/src/VBox/HostServices/DragAndDrop/dndmanager.cpp
===================================================================
--- trunk/src/VBox/HostServices/DragAndDrop/dndmanager.cpp	(revision 50477)
+++ trunk/src/VBox/HostServices/DragAndDrop/dndmanager.cpp	(revision 50508)
@@ -49,16 +49,14 @@
 public:
 
-    DnDHGSendDirPrivate(const RTCString &strPath,
-                        uint32_t fMode, uint64_t cbSize,
+    DnDHGSendDirPrivate(DnDURIObject URIObject,
                         PFNDNDPRIVATEPROGRESS pfnProgressCallback, void *pvProgressUser)
-        : m_strPath(strPath)
-        , m_cbSize(cbSize)
+        : m_URIObject(URIObject)
         , m_pfnProgressCallback(pfnProgressCallback)
         , m_pvProgressUser(pvProgressUser)
     {
         VBOXHGCMSVCPARM paTmpParms[3];
-        paTmpParms[0].setString(m_strPath.c_str());
-        paTmpParms[1].setUInt32((uint32_t)(m_strPath.length() + 1));
-        paTmpParms[2].setUInt32(fMode);
+        paTmpParms[0].setString(m_URIObject.GetDestPath().c_str());
+        paTmpParms[1].setUInt32((uint32_t)(m_URIObject.GetDestPath().length() + 1));
+        paTmpParms[2].setUInt32(m_URIObject.GetMode());
 
         m_pNextMsg = new HGCM::Message(DragAndDropSvc::HOST_DND_HG_SND_DIR, 3, paTmpParms);
@@ -71,5 +69,5 @@
         if (   RT_SUCCESS(rc)
             && m_pfnProgressCallback)
-            rc = m_pfnProgressCallback(m_cbSize, m_pvProgressUser);
+            rc = m_pfnProgressCallback(m_URIObject.GetSize(), m_pvProgressUser);
 
         return rc;
@@ -77,8 +75,8 @@
 
 protected:
-    RTCString              m_strPath;
+
+    DnDURIObject           m_URIObject;
 
     /* Progress stuff */
-    size_t                 m_cbSize;
     PFNDNDPRIVATEPROGRESS  m_pfnProgressCallback;
     void                  *m_pvProgressUser;
@@ -94,7 +92,5 @@
 public:
 
-    DnDHGSendFilePrivate(const RTCString &strHostPath,
-                         const RTCString &strGuestPath,
-                         uint32_t fMode, uint64_t cbSize,
+    DnDHGSendFilePrivate(DnDURIObject URIObject,
                          PFNDNDPRIVATEPROGRESS pfnProgressCallback, void *pvProgressUser);
     virtual ~DnDHGSendFilePrivate(void);
@@ -103,9 +99,6 @@
 
 protected:
-    RTCString              m_strHostPath;
-    RTCString              m_strGuestPath;
-    uint64_t               m_cbFileSize;
-    uint64_t               m_cbFileProcessed;
-    RTFILE                 m_hCurFile;
+
+    DnDURIObject           m_URIObject;
     VBOXHGCMSVCPARM        m_paSkelParms[5];
 
@@ -144,23 +137,18 @@
 
 /******************************************************************************
- *   DnDHGSendFilePrivate                                                *
+ *   DnDHGSendFilePrivate                                                     *
  ******************************************************************************/
 
-DnDHGSendFilePrivate::DnDHGSendFilePrivate(const RTCString &strHostPath, const RTCString &strGuestPath,
-                                           uint32_t fMode, uint64_t cbSize,
+DnDHGSendFilePrivate::DnDHGSendFilePrivate(DnDURIObject URIObject,
                                            PFNDNDPRIVATEPROGRESS pfnProgressCallback, void *pvProgressUser)
-    : m_strHostPath(strHostPath)
-    , m_strGuestPath(strGuestPath)
-    , m_cbFileSize(cbSize)
-    , m_cbFileProcessed(0)
-    , m_hCurFile(0)
+    : m_URIObject(URIObject)
     , m_pfnProgressCallback(pfnProgressCallback)
     , m_pvProgressUser(pvProgressUser)
 {
-    m_paSkelParms[0].setString(m_strGuestPath.c_str());
-    m_paSkelParms[1].setUInt32((uint32_t)(m_strGuestPath.length() + 1));
+    m_paSkelParms[0].setString(m_URIObject.GetDestPath().c_str());
+    m_paSkelParms[1].setUInt32((uint32_t)(m_URIObject.GetDestPath().length() + 1));
     m_paSkelParms[2].setPointer(NULL, 0);
     m_paSkelParms[3].setUInt32(0);
-    m_paSkelParms[4].setUInt32(fMode);
+    m_paSkelParms[4].setUInt32(m_URIObject.GetMode());
 
     m_pNextMsg = new HGCM::Message(DragAndDropSvc::HOST_DND_HG_SND_FILE, 5, m_paSkelParms);
@@ -169,6 +157,4 @@
 DnDHGSendFilePrivate::~DnDHGSendFilePrivate(void)
 {
-    if (m_hCurFile)
-        RTFileClose(m_hCurFile);
 }
 
@@ -184,13 +170,5 @@
         return rc;
 
-    if (!m_hCurFile)
-    {
-        /* Open files on the host with RTFILE_O_DENY_WRITE to prevent races where the host
-         * writes to the file while the guest transfers it over. */
-        rc = RTFileOpen(&m_hCurFile, m_strHostPath.c_str(),
-                        RTFILE_O_OPEN | RTFILE_O_READ | RTFILE_O_DENY_WRITE);
-    }
-
-    size_t cbRead;
+    uint32_t cbRead;
     if (RT_SUCCESS(rc))
     {
@@ -200,11 +178,8 @@
         void *pvBuf = paParms[2].u.pointer.addr;
         AssertPtr(pvBuf);
-        rc = RTFileRead(m_hCurFile, pvBuf, cbToRead, &cbRead);
+
+        rc = m_URIObject.Read(pvBuf, cbToRead, &cbRead);
         if (RT_LIKELY(RT_SUCCESS(rc)))
         {
-            /* Advance. */
-            m_cbFileProcessed += cbRead;
-            Assert(m_cbFileProcessed <= m_cbFileSize);
-
             /* Tell the guest the actual size. */
             paParms[3].setUInt32((uint32_t)cbRead);
@@ -214,12 +189,9 @@
     if (RT_SUCCESS(rc))
     {
-        /* Check if we are done. */
-        Assert(m_cbFileProcessed <= m_cbFileSize);
-        bool fDone = m_cbFileSize == m_cbFileProcessed;
-        if (!fDone)
+        if (!m_URIObject.IsComplete())
         {
             try
             {
-                /* More data! Prepare the next message. */
+                /* More data needed to send over. Prepare the next message. */
                 m_pNextMsg = new HGCM::Message(DragAndDropSvc::HOST_DND_HG_SND_FILE, 5 /* cParms */,
                                                m_paSkelParms);
@@ -236,11 +208,4 @@
         {
             rc = m_pfnProgressCallback(cbRead, m_pvProgressUser);
-        }
-
-        if (   fDone
-            || RT_FAILURE(rc))
-        {
-            RTFileClose(m_hCurFile);
-            m_hCurFile = NIL_RTFILE;
         }
     }
@@ -365,14 +330,14 @@
         if (!lstURIOrg.isEmpty())
         {
-            rc = m_lstURI.AppendPathsFromList(lstURIOrg, 0 /* fFlags */);
+            rc = m_lstURI.AppendNativePathsFromList(lstURIOrg, 0 /* fFlags */);
             if (RT_SUCCESS(rc))
             {
                 /* Add the total size of all meta data + files transferred to
-                 * the message's total count. */
+                 * the message's total byte count. */
                 m_cbTotal += m_lstURI.TotalBytes();
 
                 /* We have to change the actual DnD data. Remove any host paths and
-                 * just decode the filename into the new data. The guest tools will
-                 * add the correct path again, before sending the DnD drop event to
+                 * just decode the filename into the new data. The Guest Additions will
+                 * add the correct path again before sending the DnD drop event to
                  * some window. */
                 strNewURIs = m_lstURI.RootToString();
@@ -445,25 +410,24 @@
         /* Create new messages based on our internal path list. Currently
          * this could be directories or regular files. */
-        const DnDURIPath &nextPath = m_lstURI.First();
+        const DnDURIObject &nextObj = m_lstURI.First();
         try
         {
+            uint32_t fMode = nextObj.GetMode();
             LogFlowFunc(("Processing srcPath=%s, dstPath=%s, fMode=0x%x, cbSize=%RU32, fIsDir=%RTbool, fIsFile=%RTbool\n",
-                         nextPath.m_strSrcPath.c_str(), nextPath.m_strDstPath.c_str(),
-                         nextPath.m_fMode, nextPath.m_cbSize,
-                         RTFS_IS_DIRECTORY(nextPath.m_fMode), RTFS_IS_FILE(nextPath.m_fMode)));
-
-            if (RTFS_IS_DIRECTORY(nextPath.m_fMode))
-                m_pNextPathMsg = new DnDHGSendDirPrivate(nextPath.m_strDstPath,
-                                                         nextPath.m_fMode, nextPath.m_cbSize,
-                                                         &DnDHGSendDataMessage::progressCallback,
+                         nextObj.GetSourcePath().c_str(), nextObj.GetDestPath().c_str(),
+                         fMode, nextObj.GetSize(),
+                         RTFS_IS_DIRECTORY(fMode), RTFS_IS_FILE(fMode)));
+
+            if (RTFS_IS_DIRECTORY(fMode))
+                m_pNextPathMsg = new DnDHGSendDirPrivate(nextObj,
+                                                         &DnDHGSendDataMessage::progressCallback /* pfnProgressCallback */,
                                                          this /* pvProgressUser */);
-            else if (RTFS_IS_FILE(nextPath.m_fMode))
-                m_pNextPathMsg = new DnDHGSendFilePrivate(nextPath.m_strSrcPath, nextPath.m_strDstPath,
-                                                          nextPath.m_fMode, nextPath.m_cbSize,
-                                                          &DnDHGSendDataMessage::progressCallback,
+            else if (RTFS_IS_FILE(fMode))
+                m_pNextPathMsg = new DnDHGSendFilePrivate(nextObj,
+                                                          &DnDHGSendDataMessage::progressCallback /* pfnProgressCallback */,
                                                           this /* pvProgressUser */);
             else
                 AssertMsgFailedReturn(("fMode=0x%x is not supported for srcPath=%s, dstPath=%s\n",
-                                       nextPath.m_fMode, nextPath.m_strSrcPath.c_str(), nextPath.m_strDstPath.c_str()),
+                                       fMode, nextObj.GetSourcePath().c_str(), nextObj.GetDestPath().c_str()),
                                        VERR_NO_DATA);
 
Index: trunk/src/VBox/HostServices/DragAndDrop/service.cpp
===================================================================
--- trunk/src/VBox/HostServices/DragAndDrop/service.cpp	(revision 50477)
+++ trunk/src/VBox/HostServices/DragAndDrop/service.cpp	(revision 50508)
@@ -169,177 +169,248 @@
 }
 
-void DragAndDropService::guestCall(VBOXHGCMCALLHANDLE callHandle, uint32_t u32ClientID, void *pvClient, uint32_t u32Function, uint32_t cParms, VBOXHGCMSVCPARM paParms[])
+void DragAndDropService::guestCall(VBOXHGCMCALLHANDLE callHandle, uint32_t u32ClientID,
+                                   void *pvClient, uint32_t u32Function,
+                                   uint32_t cParms, VBOXHGCMSVCPARM paParms[])
 {
     LogFlowFunc(("u32ClientID=%RU32, u32Function=%RU32, cParms=%RU32\n",
                  u32ClientID, u32Function, cParms));
 
-    int rc = VINF_SUCCESS;
+    /* Check if we've the right mode set. */
+    bool fIgnoreRequest = true; /* Play safe. */
     switch (u32Function)
     {
-        /* Note: Older VBox versions with enabled DnD guest->host support (< 4.4)
-         *       used the same ID (300) for GUEST_DND_GET_NEXT_HOST_MSG and
-         *       HOST_DND_GH_REQ_PENDING, which led this service returning
-         *       VERR_INVALID_PARAMETER when the guest wanted to actually
-         *       handle HOST_DND_GH_REQ_PENDING. */
         case DragAndDropSvc::GUEST_DND_GET_NEXT_HOST_MSG:
-        {
-            LogFlowFunc(("GUEST_DND_GET_NEXT_HOST_MSG\n"));
-            if (   cParms != 3
-                || paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* message */
-                || paParms[1].type != VBOX_HGCM_SVC_PARM_32BIT /* parameter count */
-                || paParms[2].type != VBOX_HGCM_SVC_PARM_32BIT /* blocking */)
-                rc = VERR_INVALID_PARAMETER;
+            if (modeGet() != VBOX_DRAG_AND_DROP_MODE_OFF)
+            {
+                fIgnoreRequest = false;
+            }
             else
-            {
-                rc = m_pManager->nextMessageInfo(&paParms[0].u.uint32, &paParms[1].u.uint32);
-                if (   RT_FAILURE(rc)
-                    && paParms[2].u.uint32) /* Blocking? */
-                {
-                    m_clientQueue.append(new HGCM::Client(u32ClientID, callHandle, u32Function, cParms, paParms));
-                    rc = VINF_HGCM_ASYNC_EXECUTE;
-                }
-            }
+                LogFlowFunc(("Drag'n drop disabled, ignoring request\n"));
             break;
-        }
         case DragAndDropSvc::GUEST_DND_HG_ACK_OP:
-        {
-            LogFlowFunc(("GUEST_DND_HG_ACK_OP\n"));
-            if (   modeGet() != VBOX_DRAG_AND_DROP_MODE_BIDIRECTIONAL
-                && modeGet() != VBOX_DRAG_AND_DROP_MODE_HOST_TO_GUEST)
-            {
-                LogFlowFunc(("Wrong DnD mode, ignoring request\n"));
-                break;
-            }
-
-            if (   cParms != 1
-                || paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* action */)
-                rc = VERR_INVALID_PARAMETER;
+        case DragAndDropSvc::GUEST_DND_HG_REQ_DATA:
+            if (   modeGet() == VBOX_DRAG_AND_DROP_MODE_BIDIRECTIONAL
+                || modeGet() == VBOX_DRAG_AND_DROP_MODE_HOST_TO_GUEST)
+            {
+                fIgnoreRequest = false;
+            }
             else
-            {
-                DragAndDropSvc::VBOXDNDCBHGACKOPDATA data;
-                data.hdr.u32Magic = DragAndDropSvc::CB_MAGIC_DND_HG_ACK_OP;
-                paParms[0].getUInt32(&data.uAction);
-                if (m_pfnHostCallback)
-                    rc = m_pfnHostCallback(m_pvHostData, u32Function, &data, sizeof(data));
-//                m_pHelpers->pfnCallComplete(callHandle, rc);
-            }
+                LogFlowFunc(("Host -> guest DnD mode disabled, ignoring request\n"));
             break;
-        }
-        case DragAndDropSvc::GUEST_DND_HG_REQ_DATA:
-        {
-            LogFlowFunc(("GUEST_DND_HG_REQ_DATA\n"));
-            if (   modeGet() != VBOX_DRAG_AND_DROP_MODE_BIDIRECTIONAL
-                && modeGet() != VBOX_DRAG_AND_DROP_MODE_HOST_TO_GUEST)
-            {
-                LogFlowFunc(("Wrong DnD mode, ignoring request\n"));
-                break;
-            }
-
-            if (   cParms != 1
-                || paParms[0].type != VBOX_HGCM_SVC_PARM_PTR /* format */)
-                rc = VERR_INVALID_PARAMETER;
-            else
-            {
-                DragAndDropSvc::VBOXDNDCBHGREQDATADATA data;
-                data.hdr.u32Magic = DragAndDropSvc::CB_MAGIC_DND_HG_REQ_DATA;
-                uint32_t cTmp;
-                paParms[0].getPointer((void**)&data.pszFormat, &cTmp);
-                if (m_pfnHostCallback)
-                    rc = m_pfnHostCallback(m_pvHostData, u32Function, &data, sizeof(data));
-//                m_pHelpers->pfnCallComplete(callHandle, rc);
-//                if (data.pszFormat)
-//                    RTMemFree(data.pszFormat);
-//                if (data.pszTmpPath)
-//                    RTMemFree(data.pszTmpPath);
-            }
-            break;
-        }
 #ifdef VBOX_WITH_DRAG_AND_DROP_GH
         case DragAndDropSvc::GUEST_DND_GH_ACK_PENDING:
-        {
-            LogFlowFunc(("GUEST_DND_GH_ACK_PENDING\n"));
-            if (   modeGet() != VBOX_DRAG_AND_DROP_MODE_BIDIRECTIONAL
-                && modeGet() != VBOX_DRAG_AND_DROP_MODE_GUEST_TO_HOST)
-            {
-                LogFlowFunc(("Wrong DnD mode, ignoring request\n"));
-                break;
-            }
-
-            if (   cParms != 3
-                || paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* defaction */
-                || paParms[1].type != VBOX_HGCM_SVC_PARM_32BIT /* allactions */
-                || paParms[2].type != VBOX_HGCM_SVC_PARM_PTR   /* format */)
-                rc = VERR_INVALID_PARAMETER;
+        case DragAndDropSvc::GUEST_DND_GH_SND_DATA:
+        case DragAndDropSvc::GUEST_DND_GH_SND_DIR:
+        case DragAndDropSvc::GUEST_DND_GH_SND_FILE:
+        case DragAndDropSvc::GUEST_DND_GH_EVT_ERROR:
+            if (   modeGet() == VBOX_DRAG_AND_DROP_MODE_BIDIRECTIONAL
+                || modeGet() == VBOX_DRAG_AND_DROP_MODE_GUEST_TO_HOST)
+            {
+                fIgnoreRequest = false;
+            }
             else
-            {
-                DragAndDropSvc::VBOXDNDCBGHACKPENDINGDATA data;
-                data.hdr.u32Magic = DragAndDropSvc::CB_MAGIC_DND_GH_ACK_PENDING;
-                paParms[0].getUInt32(&data.uDefAction);
-                paParms[1].getUInt32(&data.uAllActions);
-                uint32_t cTmp;
-                paParms[2].getPointer((void**)&data.pszFormat, &cTmp);
-                if (m_pfnHostCallback)
-                    rc = m_pfnHostCallback(m_pvHostData, u32Function, &data, sizeof(data));
-            }
+                LogFlowFunc(("Guest -> host DnD mode disabled, ignoring request\n"));
             break;
-        }
-        case DragAndDropSvc::GUEST_DND_GH_SND_DATA:
-        {
-            LogFlowFunc(("GUEST_DND_GH_SND_DATA\n"));
-            if (   modeGet() != VBOX_DRAG_AND_DROP_MODE_BIDIRECTIONAL
-                && modeGet() != VBOX_DRAG_AND_DROP_MODE_GUEST_TO_HOST)
-            {
-                LogFlowFunc(("Wrong DnD mode, ignoring request\n"));
-                break;
-            }
-
-            if (   cParms != 2
-                || paParms[0].type != VBOX_HGCM_SVC_PARM_PTR   /* data */
-                || paParms[1].type != VBOX_HGCM_SVC_PARM_32BIT /* size */)
-                rc = VERR_INVALID_PARAMETER;
-            else
-            {
-                DragAndDropSvc::VBOXDNDCBSNDDATADATA data;
-                data.hdr.u32Magic = DragAndDropSvc::CB_MAGIC_DND_GH_SND_DATA;
-                paParms[0].getPointer((void**)&data.pvData, &data.cbData);
-                paParms[1].getUInt32(&data.cbAllSize);
-                if (m_pfnHostCallback)
-                    rc = m_pfnHostCallback(m_pvHostData, u32Function, &data, sizeof(data));
-            }
-            break;
-        }
-        case DragAndDropSvc::GUEST_DND_GH_EVT_ERROR:
-        {
-            LogFlowFunc(("GUEST_DND_GH_EVT_ERROR\n"));
-            if (   modeGet() != VBOX_DRAG_AND_DROP_MODE_BIDIRECTIONAL
-                && modeGet() != VBOX_DRAG_AND_DROP_MODE_GUEST_TO_HOST)
-            {
-                LogFlowFunc(("Wrong DnD mode, ignoring request\n"));
-                break;
-            }
-
-            if (   cParms != 1
-                || paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* rc */)
-                rc = VERR_INVALID_PARAMETER;
-            else
-            {
-                DragAndDropSvc::VBOXDNDCBEVTERRORDATA data;
-                data.hdr.u32Magic = DragAndDropSvc::CB_MAGIC_DND_GH_EVT_ERROR;
-                uint32_t rcOp;
-                paParms[0].getUInt32(&rcOp);
-                data.rc = rcOp;
-                if (m_pfnHostCallback)
-                    rc = m_pfnHostCallback(m_pvHostData, u32Function, &data, sizeof(data));
-            }
-            break;
-        }
 #endif
         default:
+            /* Reach through to DnD manager. */
+            fIgnoreRequest = false;
+            break;
+    }
+
+    int rc;
+    if (!fIgnoreRequest)
+    {
+        rc = VINF_SUCCESS;
+        switch (u32Function)
         {
-            /* All other messages are handled by the DnD manager. */
-            rc = m_pManager->nextMessage(u32Function, cParms, paParms);
-            break;
+            /* Note: Older VBox versions with enabled DnD guest->host support (< 4.4)
+             *       used the same message ID (300) for GUEST_DND_GET_NEXT_HOST_MSG and
+             *       HOST_DND_GH_REQ_PENDING, which led this service returning
+             *       VERR_INVALID_PARAMETER when the guest wanted to actually
+             *       handle HOST_DND_GH_REQ_PENDING. */
+            case DragAndDropSvc::GUEST_DND_GET_NEXT_HOST_MSG:
+            {
+                LogFlowFunc(("GUEST_DND_GET_NEXT_HOST_MSG\n"));
+                if (   cParms != 3
+                    || paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* message */
+                    || paParms[1].type != VBOX_HGCM_SVC_PARM_32BIT /* parameter count */
+                    || paParms[2].type != VBOX_HGCM_SVC_PARM_32BIT /* blocking */)
+                    rc = VERR_INVALID_PARAMETER;
+                else
+                {
+                    rc = m_pManager->nextMessageInfo(&paParms[0].u.uint32, &paParms[1].u.uint32);
+                    if (   RT_FAILURE(rc)
+                        && paParms[2].u.uint32) /* Blocking? */
+                    {
+                        m_clientQueue.append(new HGCM::Client(u32ClientID, callHandle, u32Function, cParms, paParms));
+                        rc = VINF_HGCM_ASYNC_EXECUTE;
+                    }
+                }
+                break;
+            }
+            case DragAndDropSvc::GUEST_DND_HG_ACK_OP:
+            {
+                LogFlowFunc(("GUEST_DND_HG_ACK_OP\n"));
+                if (   cParms != 1
+                    || paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* action */)
+                    rc = VERR_INVALID_PARAMETER;
+                else
+                {
+                    DragAndDropSvc::VBOXDNDCBHGACKOPDATA data;
+                    data.hdr.u32Magic = DragAndDropSvc::CB_MAGIC_DND_HG_ACK_OP;
+                    paParms[0].getUInt32(&data.uAction);
+                    if (m_pfnHostCallback)
+                        rc = m_pfnHostCallback(m_pvHostData, u32Function, &data, sizeof(data));
+    //                m_pHelpers->pfnCallComplete(callHandle, rc);
+                }
+                break;
+            }
+            case DragAndDropSvc::GUEST_DND_HG_REQ_DATA:
+            {
+                LogFlowFunc(("GUEST_DND_HG_REQ_DATA\n"));
+                if (   cParms != 1
+                    || paParms[0].type != VBOX_HGCM_SVC_PARM_PTR /* format */)
+                    rc = VERR_INVALID_PARAMETER;
+                else
+                {
+                    DragAndDropSvc::VBOXDNDCBHGREQDATADATA data;
+                    data.hdr.u32Magic = DragAndDropSvc::CB_MAGIC_DND_HG_REQ_DATA;
+                    uint32_t cTmp;
+                    paParms[0].getPointer((void**)&data.pszFormat, &cTmp);
+                    if (m_pfnHostCallback)
+                        rc = m_pfnHostCallback(m_pvHostData, u32Function, &data, sizeof(data));
+    //                m_pHelpers->pfnCallComplete(callHandle, rc);
+    //                if (data.pszFormat)
+    //                    RTMemFree(data.pszFormat);
+    //                if (data.pszTmpPath)
+    //                    RTMemFree(data.pszTmpPath);
+                }
+                break;
+            }
+#ifdef VBOX_WITH_DRAG_AND_DROP_GH
+            case DragAndDropSvc::GUEST_DND_GH_ACK_PENDING:
+            {
+                LogFlowFunc(("GUEST_DND_GH_ACK_PENDING\n"));
+                if (   cParms != 3
+                    || paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* defaction */
+                    || paParms[1].type != VBOX_HGCM_SVC_PARM_32BIT /* allactions */
+                    || paParms[2].type != VBOX_HGCM_SVC_PARM_PTR   /* format */)
+                    rc = VERR_INVALID_PARAMETER;
+                else
+                {
+                    DragAndDropSvc::VBOXDNDCBGHACKPENDINGDATA data;
+                    data.hdr.u32Magic = DragAndDropSvc::CB_MAGIC_DND_GH_ACK_PENDING;
+                    paParms[0].getUInt32(&data.uDefAction);
+                    paParms[1].getUInt32(&data.uAllActions);
+                    uint32_t cTmp;
+                    paParms[2].getPointer((void**)&data.pszFormat, &cTmp);
+                    if (m_pfnHostCallback)
+                        rc = m_pfnHostCallback(m_pvHostData, u32Function, &data, sizeof(data));
+                }
+                break;
+            }
+            case DragAndDropSvc::GUEST_DND_GH_SND_DATA:
+            {
+                LogFlowFunc(("GUEST_DND_GH_SND_DATA\n"));
+                if (   cParms != 2
+                    || paParms[0].type != VBOX_HGCM_SVC_PARM_PTR   /* data */
+                    || paParms[1].type != VBOX_HGCM_SVC_PARM_32BIT /* size */)
+                    rc = VERR_INVALID_PARAMETER;
+                else
+                {
+                    DragAndDropSvc::VBOXDNDCBSNDDATADATA data;
+                    data.hdr.u32Magic = DragAndDropSvc::CB_MAGIC_DND_GH_SND_DATA;
+                    paParms[0].getPointer((void**)&data.pvData, &data.cbData);
+                    paParms[1].getUInt32(&data.cbTotalSize);
+                    if (m_pfnHostCallback)
+                        rc = m_pfnHostCallback(m_pvHostData, u32Function, &data, sizeof(data));
+                }
+                break;
+            }
+            case DragAndDropSvc::GUEST_DND_GH_SND_DIR:
+            {
+                LogFlowFunc(("GUEST_DND_GH_SND_DIR\n"));
+                if (   cParms != 3
+                    || paParms[0].type != VBOX_HGCM_SVC_PARM_PTR   /* path */
+                    || paParms[1].type != VBOX_HGCM_SVC_PARM_32BIT /* path length */
+                    || paParms[2].type != VBOX_HGCM_SVC_PARM_32BIT /* creation mode */)
+                    rc = VERR_INVALID_PARAMETER;
+                else
+                {
+                    DragAndDropSvc::VBOXDNDCBSNDDIRDATA data;
+                    data.hdr.u32Magic = DragAndDropSvc::CB_MAGIC_DND_GH_SND_DIR;
+                    uint32_t cTmp;
+                    paParms[0].getPointer((void**)&data.pszPath, &cTmp);
+                    paParms[1].getUInt32(&data.cbPath);
+                    paParms[2].getUInt32(&data.fMode);
+#ifdef DEBUG_andy
+                    LogFlowFunc(("pszPath=%s, cbPath=%RU32, fMode=0x%x\n",
+                                 data.pszPath, data.cbPath, data.fMode));
+#endif
+                    if (m_pfnHostCallback)
+                        rc = m_pfnHostCallback(m_pvHostData, u32Function, &data, sizeof(data));
+                }
+                break;
+            }
+            case DragAndDropSvc::GUEST_DND_GH_SND_FILE:
+            {
+                LogFlowFunc(("GUEST_DND_GH_SND_FILE\n"));
+                if (   cParms != 5
+                    || paParms[0].type != VBOX_HGCM_SVC_PARM_PTR   /* file path */
+                    || paParms[1].type != VBOX_HGCM_SVC_PARM_32BIT /* file path length */
+                    || paParms[2].type != VBOX_HGCM_SVC_PARM_PTR   /* file data */
+                    || paParms[3].type != VBOX_HGCM_SVC_PARM_32BIT /* file data length */
+                    || paParms[4].type != VBOX_HGCM_SVC_PARM_32BIT /* creation mode */)
+                    rc = VERR_INVALID_PARAMETER;
+                else
+                {
+                    DragAndDropSvc::VBOXDNDCBSNDFILEDATA data;
+                    data.hdr.u32Magic = DragAndDropSvc::CB_MAGIC_DND_GH_SND_FILE;
+                    uint32_t cTmp;
+                    paParms[0].getPointer((void**)&data.pszFilePath, &cTmp);
+                    paParms[1].getUInt32(&data.cbFilePath);
+                    paParms[2].getPointer((void**)&data.pvData, &data.cbData);
+                    /* paParms[3] is cbData. */
+                    paParms[4].getUInt32(&data.fMode);
+#ifdef DEBUG_andy
+                    LogFlowFunc(("pszFilePath=%s, cbData=%RU32, pvData=0x%p, fMode=0x%x\n",
+                                 data.pszFilePath, data.cbData, data.pvData, data.fMode));
+#endif
+                    if (m_pfnHostCallback)
+                        rc = m_pfnHostCallback(m_pvHostData, u32Function, &data, sizeof(data));
+                }
+                break;
+            }
+            case DragAndDropSvc::GUEST_DND_GH_EVT_ERROR:
+            {
+                LogFlowFunc(("GUEST_DND_GH_EVT_ERROR\n"));
+                if (   cParms != 1
+                    || paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* rc */)
+                    rc = VERR_INVALID_PARAMETER;
+                else
+                {
+                    DragAndDropSvc::VBOXDNDCBEVTERRORDATA data;
+                    data.hdr.u32Magic = DragAndDropSvc::CB_MAGIC_DND_GH_EVT_ERROR;
+                    uint32_t rcOp;
+                    paParms[0].getUInt32(&rcOp);
+                    data.rc = rcOp;
+                    if (m_pfnHostCallback)
+                        rc = m_pfnHostCallback(m_pvHostData, u32Function, &data, sizeof(data));
+                }
+                break;
+            }
+#endif /* VBOX_WITH_DRAG_AND_DROP_GH */
+            default:
+            {
+                /* All other messages are handled by the DnD manager. */
+                rc = m_pManager->nextMessage(u32Function, cParms, paParms);
+                break;
+            }
         }
     }
+    else
+        rc = VERR_NOT_SUPPORTED;
+
     /* If async execute is requested, we didn't notify the guest about
      * completion. The client is queued into the waiters list and will be
