Index: trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxDnD.cpp
===================================================================
--- trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxDnD.cpp	(revision 51474)
+++ trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxDnD.cpp	(revision 51476)
@@ -668,5 +668,5 @@
     /*
      * Install our allowed MIME types.
-     ** @todo See todo for m_sstrAllowedMimeTypes in GuestDnDImpl.cpp.
+     ** @todo Also see GuestDnDPrivate.cpp.
      */
     const RTCList<RTCString> lstAllowedMimeTypes = RTCList<RTCString>()
Index: trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxDnDDataObject.cpp
===================================================================
--- trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxDnDDataObject.cpp	(revision 51474)
+++ trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxDnDDataObject.cpp	(revision 51476)
@@ -34,7 +34,7 @@
 
 #ifdef DEBUG
- /* Enable the following line to get much more debug output about
-  * (un)known clipboard formats. */
- //#define VBOX_DND_DEBUG_FORMATS
+  /* Enable the following line to get much more debug output about
+   * (un)known clipboard formats. */
+//# define VBOX_DND_DEBUG_FORMATS
 #endif
 
@@ -206,6 +206,4 @@
         return DV_E_FORMATETC;
 
-    LogFlowFunc(("pFormatEtc=%p, pMedium=%p\n", pFormatEtc, pMedium));
-
     FORMATETC *pThisFormat = &mpFormatEtc[lIndex];
     AssertPtr(pThisFormat);
@@ -213,4 +211,6 @@
     STGMEDIUM *pThisMedium = &mpStgMedium[lIndex];
     AssertPtr(pThisMedium);
+
+    LogFlowFunc(("Using pThisFormat=%p, pThisMedium=%p\n", pThisFormat, pThisMedium));
 
     HRESULT hr = DV_E_FORMATETC;
@@ -288,6 +288,4 @@
                 if (pMedium->hGlobal)
                 {
-                    /** @todo Not working yet -- needs URI to plain ASCII conversion. */
-
                     char *pcDst  = (char *)GlobalLock(pMedium->hGlobal);
                     memcpy(pcDst, mpvData, mcbData);
@@ -486,5 +484,5 @@
 const char* VBoxDnDDataObject::ClipboardFormatToString(CLIPFORMAT fmt)
 {
-#ifdef VBOX_DND_DEBUG_FORMATS
+#if 0
     char szFormat[128];
     if (GetClipboardFormatName(fmt, szFormat, sizeof(szFormat)))
Index: trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxDnDDropSource.cpp
===================================================================
--- trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxDnDDropSource.cpp	(revision 51474)
+++ trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxDnDDropSource.cpp	(revision 51476)
@@ -100,5 +100,5 @@
 STDMETHODIMP VBoxDnDDropSource::QueryContinueDrag(BOOL fEscapePressed, DWORD dwKeyState)
 {
-#ifndef DEBUG_andy
+#if 1
     LogFlowFunc(("fEscapePressed=%RTbool, dwKeyState=0x%x, mdwCurEffect=%RI32, muCurAction=%RU32\n",
                  fEscapePressed, dwKeyState, mdwCurEffect, muCurAction));
@@ -111,4 +111,5 @@
         muCurAction = DND_IGNORE_ACTION;
 
+        LogFlowFunc(("Canceled\n"));
         return DRAGDROP_S_CANCEL;
     }
@@ -116,5 +117,8 @@
     /* Left mouse button released? Start "drop" action. */
     if ((dwKeyState & MK_LBUTTON) == 0)
+    {
+        LogFlowFunc(("Dropping ...\n"));
         return DRAGDROP_S_DROP;
+    }
 
     /* No change, just continue. */
@@ -132,5 +136,5 @@
     uint32_t uAction = DND_IGNORE_ACTION;
 
-#ifndef DEBUG_andy
+#if 1
     LogFlowFunc(("dwEffect=0x%x\n", dwEffect));
 #endif
Index: trunk/src/VBox/Frontends/VBoxManage/VBoxManageControlVM.cpp
===================================================================
--- trunk/src/VBox/Frontends/VBoxManage/VBoxManageControlVM.cpp	(revision 51474)
+++ trunk/src/VBox/Frontends/VBoxManage/VBoxManageControlVM.cpp	(revision 51476)
@@ -5,5 +5,5 @@
 
 /*
- * Copyright (C) 2006-2013 Oracle Corporation
+ * Copyright (C) 2006-2014 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
@@ -198,13 +198,13 @@
             }
 
-            DragAndDropMode_T mode;
+            DnDMode_T mode;
             if (!strcmp(a->argv[2], "disabled"))
-                mode = DragAndDropMode_Disabled;
+                mode = DnDMode_Disabled;
             else if (!strcmp(a->argv[2], "hosttoguest"))
-                mode = DragAndDropMode_HostToGuest;
+                mode = DnDMode_HostToGuest;
             else if (!strcmp(a->argv[2], "guesttohost"))
-                mode = DragAndDropMode_GuestToHost;
+                mode = DnDMode_GuestToHost;
             else if (!strcmp(a->argv[2], "bidirectional"))
-                mode = DragAndDropMode_Bidirectional;
+                mode = DnDMode_Bidirectional;
             else
             {
@@ -214,5 +214,5 @@
             if (SUCCEEDED(rc))
             {
-                CHECK_ERROR_BREAK(sessionMachine, COMSETTER(DragAndDropMode)(mode));
+                CHECK_ERROR_BREAK(sessionMachine, COMSETTER(DnDMode)(mode));
             }
         }
Index: trunk/src/VBox/Frontends/VBoxManage/VBoxManageInfo.cpp
===================================================================
--- trunk/src/VBox/Frontends/VBoxManage/VBoxManageInfo.cpp	(revision 51474)
+++ trunk/src/VBox/Frontends/VBoxManage/VBoxManageInfo.cpp	(revision 51476)
@@ -1610,9 +1610,9 @@
     {
         const char *psz = "Unknown";
-        DragAndDropMode_T enmMode;
-        rc = machine->COMGETTER(DragAndDropMode)(&enmMode);
+        DnDMode_T enmMode;
+        rc = machine->COMGETTER(DnDMode)(&enmMode);
         switch (enmMode)
         {
-            case DragAndDropMode_Disabled:
+            case DnDMode_Disabled:
                 if (details == VMINFO_MACHINEREADABLE)
                     psz = "disabled";
@@ -1620,5 +1620,5 @@
                     psz = "disabled";
                 break;
-            case DragAndDropMode_HostToGuest:
+            case DnDMode_HostToGuest:
                 if (details == VMINFO_MACHINEREADABLE)
                     psz = "hosttoguest";
@@ -1626,5 +1626,5 @@
                     psz = "HostToGuest";
                 break;
-            case DragAndDropMode_GuestToHost:
+            case DnDMode_GuestToHost:
                 if (details == VMINFO_MACHINEREADABLE)
                     psz = "guesttohost";
@@ -1632,5 +1632,5 @@
                     psz = "GuestToHost";
                 break;
-            case DragAndDropMode_Bidirectional:
+            case DnDMode_Bidirectional:
                 if (details == VMINFO_MACHINEREADABLE)
                     psz = "bidirectional";
Index: trunk/src/VBox/Frontends/VBoxManage/VBoxManageModifyVM.cpp
===================================================================
--- trunk/src/VBox/Frontends/VBoxManage/VBoxManageModifyVM.cpp	(revision 51474)
+++ trunk/src/VBox/Frontends/VBoxManage/VBoxManageModifyVM.cpp	(revision 51476)
@@ -2168,13 +2168,13 @@
             case MODIFYVM_DRAGANDDROP:
             {
-                DragAndDropMode_T mode;
+                DnDMode_T mode;
                 if (!RTStrICmp(ValueUnion.psz, "disabled"))
-                    mode = DragAndDropMode_Disabled;
+                    mode = DnDMode_Disabled;
                 else if (!RTStrICmp(ValueUnion.psz, "hosttoguest"))
-                    mode = DragAndDropMode_HostToGuest;
+                    mode = DnDMode_HostToGuest;
                 else if (!RTStrICmp(ValueUnion.psz, "guesttohost"))
-                    mode = DragAndDropMode_GuestToHost;
+                    mode = DnDMode_GuestToHost;
                 else if (!RTStrICmp(ValueUnion.psz, "bidirectional"))
-                    mode = DragAndDropMode_Bidirectional;
+                    mode = DnDMode_Bidirectional;
                 else
                 {
@@ -2184,5 +2184,5 @@
                 if (SUCCEEDED(rc))
                 {
-                    CHECK_ERROR(machine, COMSETTER(DragAndDropMode)(mode));
+                    CHECK_ERROR(machine, COMSETTER(DnDMode)(mode));
                 }
                 break;
Index: trunk/src/VBox/Frontends/VirtualBox/src/UIVMInfoDialog.cpp
===================================================================
--- trunk/src/VBox/Frontends/VirtualBox/src/UIVMInfoDialog.cpp	(revision 51474)
+++ trunk/src/VBox/Frontends/VirtualBox/src/UIVMInfoDialog.cpp	(revision 51476)
@@ -606,5 +606,5 @@
         QString strClipboardMode = gpConverter->toString(m.GetClipboardMode());
         /* Determine Drag&Drop mode: */
-        QString strDragAndDropMode = gpConverter->toString(m.GetDragAndDropMode());
+        QString strDnDMode = gpConverter->toString(m.GetDnDMode());
 
         /* Deterine virtualization attributes: */
@@ -658,5 +658,5 @@
         strResult += formatValue(tr("VM Uptime"), strUptime, iMaxLength);
         strResult += formatValue(tr("Clipboard Mode"), strClipboardMode, iMaxLength);
-        strResult += formatValue(tr("Drag'n'Drop Mode"), strDragAndDropMode, iMaxLength);
+        strResult += formatValue(tr("Drag'n'Drop Mode"), strDnDMode, iMaxLength);
         strResult += formatValue(VBoxGlobal::tr("VT-x/AMD-V", "details report"), strVirtualization, iMaxLength);
         strResult += formatValue(VBoxGlobal::tr("Nested Paging", "details report"), strNestedPaging, iMaxLength);
Index: trunk/src/VBox/Frontends/VirtualBox/src/converter/UIConverterBackend.h
===================================================================
--- trunk/src/VBox/Frontends/VirtualBox/src/converter/UIConverterBackend.h	(revision 51474)
+++ trunk/src/VBox/Frontends/VirtualBox/src/converter/UIConverterBackend.h	(revision 51476)
@@ -6,5 +6,5 @@
 
 /*
- * Copyright (C) 2012 Oracle Corporation
+ * Copyright (C) 2012-2014 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
@@ -88,5 +88,5 @@
 template<> bool canConvert<KDeviceType>();
 template<> bool canConvert<KClipboardMode>();
-template<> bool canConvert<KDragAndDropMode>();
+template<> bool canConvert<KDnDMode>();
 template<> bool canConvert<KPointingHIDType>();
 template<> bool canConvert<KMediumType>();
@@ -161,5 +161,5 @@
 template<> QString toString(const KDeviceType &type);
 template<> QString toString(const KClipboardMode &mode);
-template<> QString toString(const KDragAndDropMode &mode);
+template<> QString toString(const KDnDMode &mode);
 template<> QString toString(const KPointingHIDType &type);
 template<> QString toString(const KMediumType &type);
Index: trunk/src/VBox/Frontends/VirtualBox/src/converter/UIConverterBackendCOM.cpp
===================================================================
--- trunk/src/VBox/Frontends/VirtualBox/src/converter/UIConverterBackendCOM.cpp	(revision 51474)
+++ trunk/src/VBox/Frontends/VirtualBox/src/converter/UIConverterBackendCOM.cpp	(revision 51476)
@@ -7,5 +7,5 @@
 
 /*
- * Copyright (C) 2012-2013 Oracle Corporation
+ * Copyright (C) 2012-2014 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
@@ -34,5 +34,5 @@
 template<> bool canConvert<KDeviceType>() { return true; }
 template<> bool canConvert<KClipboardMode>() { return true; }
-template<> bool canConvert<KDragAndDropMode>() { return true; }
+template<> bool canConvert<KDnDMode>() { return true; }
 template<> bool canConvert<KPointingHIDType>() { return true; }
 template<> bool canConvert<KMediumType>() { return true; }
@@ -202,13 +202,13 @@
 }
 
-/* QString <= KDragAndDropMode: */
-template<> QString toString(const KDragAndDropMode &mode)
+/* QString <= KDnDMode: */
+template<> QString toString(const KDnDMode &mode)
 {
     switch (mode)
     {
-        case KDragAndDropMode_Disabled:      return QApplication::translate("VBoxGlobal", "Disabled", "DragAndDropType");
-        case KDragAndDropMode_HostToGuest:   return QApplication::translate("VBoxGlobal", "Host To Guest", "DragAndDropType");
-        case KDragAndDropMode_GuestToHost:   return QApplication::translate("VBoxGlobal", "Guest To Host", "DragAndDropType");
-        case KDragAndDropMode_Bidirectional: return QApplication::translate("VBoxGlobal", "Bidirectional", "DragAndDropType");
+        case KDnDMode_Disabled:      return QApplication::translate("VBoxGlobal", "Disabled", "DragAndDropType");
+        case KDnDMode_HostToGuest:   return QApplication::translate("VBoxGlobal", "Host To Guest", "DragAndDropType");
+        case KDnDMode_GuestToHost:   return QApplication::translate("VBoxGlobal", "Guest To Host", "DragAndDropType");
+        case KDnDMode_Bidirectional: return QApplication::translate("VBoxGlobal", "Bidirectional", "DragAndDropType");
         default: AssertMsgFailed(("No text for %d", mode)); break;
     }
Index: trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIDnDDataObject_win.cpp
===================================================================
--- trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIDnDDataObject_win.cpp	(revision 51474)
+++ trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIDnDDataObject_win.cpp	(revision 51476)
@@ -41,7 +41,9 @@
 
 UIDnDDataObject::UIDnDDataObject(CSession &session,
+                                 CDnDSource &dndSource,
                                  const QStringList &lstFormats,
                                  QWidget *pParent)
     : mSession(session),
+      mDnDSource(dndSource),
       mpParent(pParent),
       mStatus(Uninitialized),
@@ -65,5 +67,7 @@
         RT_BZERO(mpStgMedium, sizeof(STGMEDIUM) * cMaxFormats);
 
-        for (int i = 0; i < lstFormats.size(); i++)
+        for (int i = 0;
+             (   i < lstFormats.size()
+              && i < cMaxFormats); i++)
         {
             const QString &strFormat = lstFormats.at(i);
@@ -95,5 +99,5 @@
         }
 
-        LogFlowFunc(("Total registered formats: %RU32 (of %d total)\n",
+        LogFlowFunc(("Total registered native formats: %RU32 (for %d formats from guest)\n",
                      cRegisteredFormats, lstFormats.size()));
         hr = S_OK;
@@ -290,4 +294,6 @@
         {
             rc = UIDnDDrag::RetrieveData(mSession,
+                                         mDnDSource,
+                                         /** @todo Support other actions. */
                                          Qt::CopyAction,
                                          strMIMEType, vaType, mVaData,
Index: trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIDnDDataObject_win.h
===================================================================
--- trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIDnDDataObject_win.h	(revision 51474)
+++ trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIDnDDataObject_win.h	(revision 51476)
@@ -29,4 +29,5 @@
 /* COM includes: */
 #include "COMEnums.h"
+#include "CDndSource.h"
 #include "CSession.h"
 
@@ -49,5 +50,5 @@
 public:
 
-    UIDnDDataObject(CSession &session, const QStringList &lstFormats, QWidget *pParent);
+    UIDnDDataObject(CSession &session, CDnDSource &dndSource, const QStringList &lstFormats, QWidget *pParent);
     virtual ~UIDnDDataObject(void);
 
@@ -87,4 +88,5 @@
     QWidget    *mpParent;
     CSession    mSession;
+    CDnDSource  mDnDSource;
     Status      mStatus;
     LONG        mRefCount;
Index: trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIDnDDrag.cpp
===================================================================
--- trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIDnDDrag.cpp	(revision 51474)
+++ trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIDnDDrag.cpp	(revision 51476)
@@ -44,9 +44,11 @@
 #endif
 
-UIDnDDrag::UIDnDDrag(CSession &session, 
+UIDnDDrag::UIDnDDrag(CSession &session,
+                     CDnDSource &dndSource,
                      const QStringList &lstFormats,
                      Qt::DropAction defAction, Qt::DropActions actions,
                      QWidget *pParent /* = NULL */)
     : m_session(session)
+    , m_dndSource(dndSource)
     , m_lstFormats(lstFormats)
     , m_defAction(defAction)
@@ -72,5 +74,5 @@
 #ifdef RT_OS_WINDOWS
     UIDnDDropSource *pDropSource = new UIDnDDropSource(m_pParent);
-    UIDnDDataObject *pDataObject = new UIDnDDataObject(m_session, m_lstFormats, m_pParent);
+    UIDnDDataObject *pDataObject = new UIDnDDataObject(m_session, m_dndSource, m_lstFormats, m_pParent);
 
     DWORD dwOKEffects = DROPEFFECT_NONE;
@@ -86,8 +88,9 @@
 
     DWORD dwEffect;
+    LogFlowFunc(("dwOKEffects=0x%x\n", dwOKEffects));
     HRESULT hr = ::DoDragDrop(pDataObject, pDropSource,
                               dwOKEffects, &dwEffect);
-    LogFlowThisFunc(("DoDragDrop ended with hr=%Rhrc, dwEffect=%RI32\n",
-                     hr, dwEffect));
+    LogFlowFunc(("DoDragDrop ended with hr=%Rhrc, dwEffect=%RI32\n",
+                 hr, dwEffect));
 
     if (pDropSource)
@@ -99,5 +102,5 @@
 
     /* pMData is transfered to the QDrag object, so no need for deletion. */
-    pMData = new UIDnDMimeData(m_session, 
+    pMData = new UIDnDMimeData(m_session, m_dndSource,
                                m_lstFormats, m_defAction, m_actions,
                                m_pParent);
@@ -129,4 +132,5 @@
 /* static */
 int UIDnDDrag::RetrieveData(const CSession &session,
+                            CDnDSource &dndSource,
                             Qt::DropAction dropAction,
                             const QString &strMimeType,
@@ -140,8 +144,8 @@
     CGuest guest = session.GetConsole().GetGuest();
 
-    /* Start getting the data from the guest. First inform the guest we
+    /* Start getting the data from the source. First inform the source we
      * want the data in the specified MIME type. */
-    CProgress progress = guest.DragGHDropped(strMimeType,
-                                             UIDnDHandler::toVBoxDnDAction(dropAction));
+    CProgress progress = dndSource.Drop(strMimeType,
+                                        UIDnDHandler::toVBoxDnDAction(dropAction));
     if (guest.isOk())
     {
@@ -157,6 +161,7 @@
             if (RT_SUCCESS(rc))
             {
-                /* After the data successfully arrived from the guest, we query it from Main. */
-                QVector<uint8_t> vecData = guest.DragGHGetData();
+                /* After we successfully retrieved data from
+                * the source, we query it from Main. */
+                QVector<uint8_t> vecData = dndSource.ReceiveData();
                 if (!vecData.isEmpty())
                 {
Index: trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIDnDDrag.h
===================================================================
--- trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIDnDDrag.h	(revision 51474)
+++ trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIDnDDrag.h	(revision 51476)
@@ -28,4 +28,5 @@
 #include "CSession.h"
 #include "CConsole.h"
+#include "CDnDSource.h"
 #include "CGuest.h"
 
@@ -45,5 +46,5 @@
 public:
 
-    UIDnDDrag(CSession &session, 
+    UIDnDDrag(CSession &session, CDnDSource &dndSource,
               const QStringList &lstFormats, Qt::DropAction defAction, Qt::DropActions actions,
               QWidget *pParent = NULL);
@@ -54,9 +55,10 @@
 public:
 
-    static int RetrieveData(const CSession &session, Qt::DropAction dropAction, const QString &strMimeType, QVariant::Type vaType, QVariant &vaData, QWidget *pParent);
+    static int RetrieveData(const CSession &session, CDnDSource &dndSource, Qt::DropAction dropAction, const QString &strMimeType, QVariant::Type vaType, QVariant &vaData, QWidget *pParent);
 
 private:
 
     CSession          m_session;
+    CDnDSource        m_dndSource;
     QStringList       m_lstFormats;
     Qt::DropAction    m_defAction;
Index: trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIDnDHandler.cpp
===================================================================
--- trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIDnDHandler.cpp	(revision 51474)
+++ trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIDnDHandler.cpp	(revision 51476)
@@ -34,4 +34,5 @@
 #include "UIDnDHandler.h"
 #ifdef VBOX_WITH_DRAG_AND_DROP_GH
+# include "CDnDSource.h"
 # include "UIDnDDrag.h"
 #endif
@@ -39,47 +40,44 @@
 
 /* COM includes: */
+#include "CConsole.h"
+#include "CDnDTarget.h"
+#include "CGuest.h"
 #include "CSession.h"
-#include "CConsole.h"
-#include "CGuest.h"
+
+
 
 UIDnDHandler *UIDnDHandler::m_pInstance = NULL;
 
 UIDnDHandler::UIDnDHandler(void)
-    : mMode(Unknown)
 {
 }
 
 /*
- * Host -> Guest
- */
-
-Qt::DropAction UIDnDHandler::dragHGEnter(CGuest &guest, ulong screenId, int x, int y,
-                                         Qt::DropAction proposedAction, Qt::DropActions possibleActions,
-                                         const QMimeData *pMimeData, QWidget * /* pParent = NULL */)
-{
-    if (mMode == GH) /* Wrong mode? Bail out. */
-        return Qt::IgnoreAction;
-
+ * Frontend -> Target.
+ */
+
+Qt::DropAction UIDnDHandler::dragEnter(CDnDTarget &dndTarget, ulong screenId, int x, int y,
+                                       Qt::DropAction proposedAction, Qt::DropActions possibleActions,
+                                       const QMimeData *pMimeData, QWidget * /* pParent = NULL */)
+{
     LogFlowFunc(("screenId=%RU32, x=%d, y=%d, action=%ld\n",
                  screenId, x, y, toVBoxDnDAction(proposedAction)));
 
     /* Ask the guest for starting a DnD event. */
-    KDragAndDropAction result = guest.DragHGEnter(screenId,
-                                                  x,
-                                                  y,
-                                                  toVBoxDnDAction(proposedAction),
-                                                  toVBoxDnDActions(possibleActions),
-                                                  pMimeData->formats().toVector());
+    KDnDAction result = dndTarget.Enter(screenId,
+                                        x,
+                                        y,
+                                        toVBoxDnDAction(proposedAction),
+                                        toVBoxDnDActions(possibleActions),
+                                        pMimeData->formats().toVector());
+
     /* Set the DnD action returned by the guest. */
     return toQtDnDAction(result);
 }
 
-Qt::DropAction UIDnDHandler::dragHGMove(CGuest &guest, ulong screenId, int x, int y,
-                                        Qt::DropAction proposedAction, Qt::DropActions possibleActions,
-                                        const QMimeData *pMimeData, QWidget * /* pParent = NULL */)
-{
-    if (mMode == GH) /* Wrong mode? Bail out. */
-        return Qt::IgnoreAction;
-
+Qt::DropAction UIDnDHandler::dragMove(CDnDTarget &dndTarget, ulong screenId, int x, int y,
+                                      Qt::DropAction proposedAction, Qt::DropActions possibleActions,
+                                      const QMimeData *pMimeData, QWidget * /* pParent = NULL */)
+{
 #ifdef DEBUG_andy
     LogFlowFunc(("screenId=%RU32, x=%d, y=%d, action=%ld\n",
@@ -89,20 +87,20 @@
     /* Notify the guest that the mouse has been moved while doing
      * a drag'n drop operation. */
-    KDragAndDropAction result = guest.DragHGMove(screenId,
-                                                 x,
-                                                 y,
-                                                 toVBoxDnDAction(proposedAction),
-                                                 toVBoxDnDActions(possibleActions),
-                                                 pMimeData->formats().toVector());
+    KDnDAction result = dndTarget.Move(screenId,
+                                       x,
+                                       y,
+                                       toVBoxDnDAction(proposedAction),
+                                       toVBoxDnDActions(possibleActions),
+                                       pMimeData->formats().toVector());
     /* Set the DnD action returned by the guest. */
     return toQtDnDAction(result);
 }
 
-Qt::DropAction UIDnDHandler::dragHGDrop(CGuest &guest, ulong screenId, int x, int y,
-                                        Qt::DropAction proposedAction, Qt::DropActions possibleActions,
-                                        const QMimeData *pMimeData, QWidget *pParent /* = NULL */)
-{
-    if (mMode == GH) /* Wrong mode? Bail out. */
-        return Qt::IgnoreAction;
+Qt::DropAction UIDnDHandler::dragDrop(CSession &session, CDnDTarget &dndTarget,
+                                      ulong screenId, int x, int y,
+                                      Qt::DropAction proposedAction, Qt::DropActions possibleActions,
+                                      const QMimeData *pMimeData, QWidget *pParent /* = NULL */)
+{
+    CGuest guest = session.GetConsole().GetGuest();
 
     LogFlowFunc(("screenId=%RU32, x=%d, y=%d, action=%ld\n",
@@ -112,14 +110,15 @@
     QString format;
     /* Ask the guest for dropping data. */
-    KDragAndDropAction result = guest.DragHGDrop(screenId,
-                                                 x,
-                                                 y,
-                                                 toVBoxDnDAction(proposedAction),
-                                                 toVBoxDnDActions(possibleActions),
-                                                 pMimeData->formats().toVector(), format);
+    KDnDAction result = dndTarget.Drop(screenId,
+                                       x,
+                                       y,
+                                       toVBoxDnDAction(proposedAction),
+                                       toVBoxDnDActions(possibleActions),
+                                       pMimeData->formats().toVector(), format);
     /* Has the guest accepted the drop event? */
-    if (result != KDragAndDropAction_Ignore)
+    if (result != KDnDAction_Ignore)
     {
         /* Get the actual MIME data in the requested format. */
+        AssertPtr(pMimeData);
         const QByteArray &d = pMimeData->data(format);
         if (   !d.isEmpty()
@@ -131,5 +130,5 @@
             memcpy(dv.data(), d.constData(), d.size());
 
-            CProgress progress = guest.DragHGPutData(screenId, format, dv);
+            CProgress progress = dndTarget.SendData(screenId, format, dv);
             if (guest.isOk())
             {
@@ -142,5 +141,5 @@
                 {
                     msgCenter().cannotDropData(progress, pParent);
-                    result = KDragAndDropAction_Ignore;
+                    result = KDnDAction_Ignore;
                 }
             }
@@ -148,5 +147,5 @@
             {
                 msgCenter().cannotDropData(guest, pParent);
-                result = KDragAndDropAction_Ignore;
+                result = KDnDAction_Ignore;
             }
         }
@@ -156,25 +155,25 @@
 }
 
-void UIDnDHandler::dragHGLeave(CGuest &guest, ulong screenId, QWidget * /* pParent = NULL */)
-{
-    if (mMode == GH) /* Wrong mode? Bail out. */
-        return;
-
+void UIDnDHandler::dragLeave(CDnDTarget &dndTarget,
+                             ulong screenId, QWidget * /* pParent = NULL */)
+{
     LogFlowFunc(("screenId=%RU32\n", screenId));
-    guest.DragHGLeave(screenId);
-}
-
-int UIDnDHandler::dragGHPending(CSession &session, ulong screenId, QWidget *pParent /* = NULL */)
+    dndTarget.Leave(screenId);
+}
+
+/*
+ * Source -> Frontend.
+ */
+
+int UIDnDHandler::dragIsPending(CSession &session, CDnDSource &dndSource,
+                                ulong screenId, QWidget *pParent /* = NULL */)
 {
     int rc;
 #ifdef VBOX_WITH_DRAG_AND_DROP_GH
-    if (mMode == HG) /* Wrong mode? Bail out. */
-        return VERR_WRONG_ORDER;
-
     /*
-     * How this works: Host is asking the guest if there is any DnD
-     * operation pending, when the mouse leaves the guest window
-     * (DragGHPending). On return there is some info about a running DnD
-     * operation (or defaultAction is KDragAndDropAction_Ignore if not). With
+     * How this works: Source is asking the target if there is any DnD
+     * operation pending, when the mouse leaves the guest window. On
+     * return there is some info about a running DnD operation
+     * (or defaultAction is KDnDAction_Ignore if not). With
      * this information we create a Qt QDrag object with our own QMimeType
      * implementation and call exec. Please note, this *blocks* until the DnD
@@ -183,10 +182,10 @@
     CGuest guest = session.GetConsole().GetGuest();
     QVector<QString> vecFmtGuest;
-    QVector<KDragAndDropAction> vecActions;
-    KDragAndDropAction defaultAction = guest.DragGHPending(screenId, vecFmtGuest, vecActions);
+    QVector<KDnDAction> vecActions;
+    KDnDAction defaultAction = dndSource.DragIsPending(screenId, vecFmtGuest, vecActions);
     LogFlowFunc(("defaultAction=%d, numFormats=%d\n", defaultAction, vecFmtGuest.size()));
 
     QStringList lstFmtNative;
-    if (defaultAction != KDragAndDropAction_Ignore)
+    if (defaultAction != KDnDAction_Ignore)
     {
         /*
@@ -234,13 +233,20 @@
     if (!lstFmtNative.isEmpty())
     {
-        UIDnDDrag *pDrag = new UIDnDDrag(session, lstFmtNative,
-                                         toQtDnDAction(defaultAction),
-                                         toQtDnDActions(vecActions), pParent);
-        rc = pDrag->DoDragDrop();
-
-        delete pDrag;
+        try
+        {
+            UIDnDDrag *pDrag = new UIDnDDrag(session, dndSource, lstFmtNative,
+                                             toQtDnDAction(defaultAction),
+                                             toQtDnDActions(vecActions), pParent);
+            rc = pDrag->DoDragDrop();
+
+            delete pDrag;
+        }
+        catch (std::bad_alloc &)
+        {
+            rc = VERR_NO_MEMORY;
+        }
     }
-    else
-        rc = VINF_SUCCESS;
+    else /* No format data from the guest arrived yet. */
+        rc = VERR_NO_DATA;
 #else /* !VBOX_WITH_DRAG_AND_DROP_GH */
     NOREF(session);
@@ -260,28 +266,28 @@
 
 /* static */
-KDragAndDropAction UIDnDHandler::toVBoxDnDAction(Qt::DropAction action)
+KDnDAction UIDnDHandler::toVBoxDnDAction(Qt::DropAction action)
 {
     if (action == Qt::CopyAction)
-        return KDragAndDropAction_Copy;
+        return KDnDAction_Copy;
     if (action == Qt::MoveAction)
-        return KDragAndDropAction_Move;
+        return KDnDAction_Move;
     if (action == Qt::LinkAction)
-        return KDragAndDropAction_Link;
-
-    return KDragAndDropAction_Ignore;
+        return KDnDAction_Link;
+
+    return KDnDAction_Ignore;
 }
 
 /* static */
-QVector<KDragAndDropAction> UIDnDHandler::toVBoxDnDActions(Qt::DropActions actions)
-{
-    QVector<KDragAndDropAction> vbActions;
+QVector<KDnDAction> UIDnDHandler::toVBoxDnDActions(Qt::DropActions actions)
+{
+    QVector<KDnDAction> vbActions;
     if (actions.testFlag(Qt::IgnoreAction))
-        vbActions << KDragAndDropAction_Ignore;
+        vbActions << KDnDAction_Ignore;
     if (actions.testFlag(Qt::CopyAction))
-        vbActions << KDragAndDropAction_Copy;
+        vbActions << KDnDAction_Copy;
     if (actions.testFlag(Qt::MoveAction))
-        vbActions << KDragAndDropAction_Move;
+        vbActions << KDnDAction_Move;
     if (actions.testFlag(Qt::LinkAction))
-        vbActions << KDragAndDropAction_Link;
+        vbActions << KDnDAction_Link;
 
     return vbActions;
@@ -289,12 +295,12 @@
 
 /* static */
-Qt::DropAction UIDnDHandler::toQtDnDAction(KDragAndDropAction action)
+Qt::DropAction UIDnDHandler::toQtDnDAction(KDnDAction action)
 {
     Qt::DropAction dropAct = Qt::IgnoreAction;
-    if (action == KDragAndDropAction_Copy)
+    if (action == KDnDAction_Copy)
         dropAct = Qt::CopyAction;
-    if (action == KDragAndDropAction_Move)
+    if (action == KDnDAction_Move)
         dropAct = Qt::MoveAction;
-    if (action == KDragAndDropAction_Link)
+    if (action == KDnDAction_Link)
         dropAct = Qt::LinkAction;
 
@@ -304,5 +310,5 @@
 
 /* static */
-Qt::DropActions UIDnDHandler::toQtDnDActions(const QVector<KDragAndDropAction> &vecActions)
+Qt::DropActions UIDnDHandler::toQtDnDActions(const QVector<KDnDAction> &vecActions)
 {
     Qt::DropActions dropActs = Qt::IgnoreAction;
@@ -311,14 +317,14 @@
         switch (vecActions.at(i))
         {
-            case KDragAndDropAction_Ignore:
+            case KDnDAction_Ignore:
                 dropActs |= Qt::IgnoreAction;
                 break;
-            case KDragAndDropAction_Copy:
+            case KDnDAction_Copy:
                 dropActs |= Qt::CopyAction;
                 break;
-            case KDragAndDropAction_Move:
+            case KDnDAction_Move:
                 dropActs |= Qt::MoveAction;
                 break;
-            case KDragAndDropAction_Link:
+            case KDnDAction_Link:
                 dropActs |= Qt::LinkAction;
                 break;
Index: trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIDnDHandler.h
===================================================================
--- trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIDnDHandler.h	(revision 51474)
+++ trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIDnDHandler.h	(revision 51476)
@@ -3,5 +3,5 @@
  *
  * VBox frontends: Qt GUI ("VirtualBox"):
- * UIDnDHandler class declaration
+ * UIDnDHandler class declaration.
  */
 
@@ -26,6 +26,8 @@
 /* Forward declarations: */
 class QMimeData;
+class CDnDSource;
+class CDnDTarget;
+class CGuest;
 class CSession;
-class CGuest;
 class UIDnDMimeData;
 
@@ -37,5 +39,5 @@
 
     /* Singleton factory. */
-    static UIDnDHandler* instance(void)
+    static UIDnDHandler *instance(void)
     {
         if (!m_pInstance)
@@ -56,41 +58,44 @@
      * Current operation mode.
      */
-    enum Mode
+    enum Direction
     {
         /** Unknown mode. */
         Unknown = 0,
         /** Host to guest. */
-        HG,
+        HostToGuest,
         /** Guest to host. */
-        GH
+        GuestToHost
+        /** @todo Implement guest to guest. */
     };
 
-    /* Host -> Guest. */
-    Qt::DropAction dragHGEnter(CGuest &guest, ulong screenId, int x, int y, Qt::DropAction proposedAction, Qt::DropActions possibleActions, const QMimeData *pMimeData, QWidget *pParent = NULL);
-    Qt::DropAction dragHGMove (CGuest &guest, ulong screenId, int x, int y, Qt::DropAction proposedAction, Qt::DropActions possibleActions, const QMimeData *pMimeData, QWidget *pParent = NULL);
-    Qt::DropAction dragHGDrop (CGuest &guest, ulong screenId, int x, int y, Qt::DropAction proposedAction, Qt::DropActions possibleActions, const QMimeData *pMimeData, QWidget *pParent = NULL);
-    void           dragHGLeave(CGuest &guest, ulong screenId, QWidget *pParent = NULL);
+    /* Frontend -> Target. */
+    Qt::DropAction             dragEnter(CDnDTarget &dndTarget, ulong screenId, int x, int y, Qt::DropAction proposedAction, Qt::DropActions possibleActions, const QMimeData *pMimeData, QWidget *pParent = NULL);
+    Qt::DropAction             dragMove (CDnDTarget &dndTarget, ulong screenId, int x, int y, Qt::DropAction proposedAction, Qt::DropActions possibleActions, const QMimeData *pMimeData, QWidget *pParent = NULL);
+    Qt::DropAction             dragDrop (CSession &session, CDnDTarget &dndTarget, ulong screenId, int x, int y, Qt::DropAction proposedAction, Qt::DropActions possibleActions, const QMimeData *pMimeData, QWidget *pParent = NULL);
+    void                       dragLeave(CDnDTarget &dndTarget, ulong screenId, QWidget *pParent = NULL);
 
-    /* Guest -> Host. */
-    int            dragGHPending(CSession &session, ulong screenId, QWidget *pParent = NULL);
+    /* Source -> Frontend. */
+    int                        dragIsPending(CSession &session, CDnDSource &dndSource, ulong screenId, QWidget *pParent = NULL);
 
 public:
 
-    static KDragAndDropAction          toVBoxDnDAction(Qt::DropAction action);
-    static QVector<KDragAndDropAction> toVBoxDnDActions(Qt::DropActions actions);
-    static Qt::DropAction              toQtDnDAction(KDragAndDropAction action);
-    static Qt::DropActions             toQtDnDActions(const QVector<KDragAndDropAction> &vecActions);
+    static KDnDAction          toVBoxDnDAction(Qt::DropAction action);
+    static QVector<KDnDAction> toVBoxDnDActions(Qt::DropActions actions);
+    static Qt::DropAction      toQtDnDAction(KDnDAction action);
+    static Qt::DropActions     toQtDnDActions(const QVector<KDnDAction> &vecActions);
 
 private:
-    static UIDnDHandler *m_pInstance;
 
     UIDnDHandler(void);
     virtual ~UIDnDHandler(void) {}
 
-    /** The current operation mode. */
-    Mode mMode;
+private:
+
+    /** Static pointer to singleton instance. */
+    static UIDnDHandler *m_pInstance;
 };
 
-#define gDnD UIDnDHandler::instance()
+/** Gets the singleton instance of the drag'n drop UI helper class. */
+#define DnDHandler() UIDnDHandler::instance()
 
 #endif /* ___UIDnDHandler_h___ */
Index: trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIDnDMIMEData.cpp
===================================================================
--- trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIDnDMIMEData.cpp	(revision 51474)
+++ trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIDnDMIMEData.cpp	(revision 51476)
@@ -38,9 +38,11 @@
 #include "UIMessageCenter.h"
 
-UIDnDMimeData::UIDnDMimeData(CSession &session, 
+UIDnDMimeData::UIDnDMimeData(CSession &session,
+                             CDnDSource &dndSource,
                              QStringList formats,
                              Qt::DropAction defAction, Qt::DropActions actions,
                              QWidget *pParent)
     : m_Session(session)
+    , m_DnDSource(dndSource)
     , m_lstFormats(formats)
     , m_defAction(defAction)
@@ -109,5 +111,5 @@
 
 QVariant UIDnDMimeData::retrieveData(const QString &strMIMEType,
-                                     QVariant::Type vaType) const
+                                     QVariant::Type vaType)
 {
     LogFlowFunc(("m_enmState=%d, mimeType=%s, type=%d (%s)\n",
@@ -165,4 +167,5 @@
     {
         rc = UIDnDDrag::RetrieveData(m_Session,
+                                     m_DnDSource,
                                      m_defAction,
                                      strMIMEType, vaType, m_vaData,
@@ -198,5 +201,5 @@
                 LogFlowFunc(("MouseMove: x=%d, y=%d\n",
                              pMouseEvent->globalX(), pMouseEvent->globalY()));
-                
+
                 return true;
                 /* Never reached. */
@@ -207,5 +210,5 @@
                 LogFlowFunc(("MouseButtonRelease\n"));
                 m_enmState = Dropped;
-                
+
                 return true;
                 /* Never reached. */
@@ -220,5 +223,5 @@
                     m_enmState = Canceled;
                 }
-                
+
                 return true;
                 /* Never reached. */
Index: trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIDnDMIMEData.h
===================================================================
--- trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIDnDMIMEData.h	(revision 51474)
+++ trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIDnDMIMEData.h	(revision 51476)
@@ -26,7 +26,8 @@
 /* COM includes: */
 #include "COMEnums.h"
+#include "CConsole.h"
+#include "CDnDSource.h"
+#include "CGuest.h"
 #include "CSession.h"
-#include "CConsole.h"
-#include "CGuest.h"
 
 #include "UIDnDHandler.h"
@@ -61,5 +62,5 @@
 public:
 
-    UIDnDMimeData(CSession &session, QStringList formats, Qt::DropAction defAction, Qt::DropActions actions, QWidget *pParent);
+    UIDnDMimeData(CSession &session, CDnDSource &dndSource, QStringList formats, Qt::DropAction defAction, Qt::DropActions actions, QWidget *pParent);
 
 public:
@@ -78,5 +79,5 @@
     virtual bool hasFormat(const QString &mimeType) const;
 
-    virtual QVariant retrieveData(const QString &mimeType, QVariant::Type type) const;
+    virtual QVariant retrieveData(const QString &mimeType, QVariant::Type type);
 
 #ifndef RT_OS_WINDOWS
@@ -98,4 +99,5 @@
 
     CSession          m_Session;
+    CDnDSource        m_DnDSource;
     QStringList       m_lstFormats;
     Qt::DropAction    m_defAction;
Index: trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineLogic.cpp
===================================================================
--- trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineLogic.cpp	(revision 51474)
+++ trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineLogic.cpp	(revision 51476)
@@ -5,5 +5,5 @@
 
 /*
- * Copyright (C) 2010-2013 Oracle Corporation
+ * Copyright (C) 2010-2014 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
@@ -729,5 +729,5 @@
     {
         foreach (QAction *pAction, m_pDragAndDropActions->actions())
-            pAction->setText(gpConverter->toString(pAction->data().value<KDragAndDropMode>()));
+            pAction->setText(gpConverter->toString(pAction->data().value<KDnDMode>()));
     }
 }
@@ -1864,12 +1864,12 @@
     {
         m_pDragAndDropActions = new QActionGroup(this);
-        for (int i = KDragAndDropMode_Disabled; i < KDragAndDropMode_Max; ++i)
+        for (int i = KDnDMode_Disabled; i < KDnDMode_Max; ++i)
         {
-            KDragAndDropMode mode = (KDragAndDropMode)i;
+            KDnDMode mode = (KDnDMode)i;
             QAction *pAction = new QAction(gpConverter->toString(mode), m_pDragAndDropActions);
             pMenu->addAction(pAction);
             pAction->setData(QVariant::fromValue(mode));
             pAction->setCheckable(true);
-            pAction->setChecked(session().GetMachine().GetDragAndDropMode() == mode);
+            pAction->setChecked(session().GetMachine().GetDnDMode() == mode);
         }
         connect(m_pDragAndDropActions, SIGNAL(triggered(QAction*)),
@@ -1879,5 +1879,5 @@
     else
         foreach (QAction *pAction, m_pDragAndDropActions->actions())
-            if (pAction->data().value<KDragAndDropMode>() == session().GetMachine().GetDragAndDropMode())
+            if (pAction->data().value<KDnDMode>() == session().GetMachine().GetDnDMode())
                 pAction->setChecked(true);
 }
@@ -1961,6 +1961,6 @@
 {
     /* Assign new mode (without save): */
-    KDragAndDropMode mode = pAction->data().value<KDragAndDropMode>();
-    session().GetMachine().SetDragAndDropMode(mode);
+    KDnDMode mode = pAction->data().value<KDnDMode>();
+    session().GetMachine().SetDnDMode(mode);
 }
 
Index: trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineView.cpp
===================================================================
--- trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineView.cpp	(revision 51474)
+++ trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineView.cpp	(revision 51476)
@@ -61,5 +61,9 @@
 #include "CFramebuffer.h"
 #ifdef VBOX_WITH_DRAG_AND_DROP
+# include "CDnDSource.h"
+# include "CDnDTarget.h"
 # include "CGuest.h"
+# include "CGuestDnDTarget.h"
+# include "CGuestDnDSource.h"
 #endif /* VBOX_WITH_DRAG_AND_DROP */
 
@@ -1160,18 +1164,20 @@
 void UIMachineView::dragEnterEvent(QDragEnterEvent *pEvent)
 {
-    /* The guest object to talk to. */
+    AssertPtrReturnVoid(pEvent);
+
+    /* Get mouse-pointer location. */
+    const QPoint &cpnt = viewportToContents(pEvent->pos());
+
     CGuest guest = session().GetConsole().GetGuest();
-
-    /* Get mouse-pointer location */
-    const QPoint &cpnt = viewportToContents(pEvent->pos());
-
-    /* Ask the guest for starting a DnD event. */
-    Qt::DropAction result = gDnD->dragHGEnter(guest,
-                                              screenId(),
-                                              frameBuffer()->convertHostXTo(cpnt.x()),
-                                              frameBuffer()->convertHostYTo(cpnt.y()),
-                                              pEvent->proposedAction(),
-                                              pEvent->possibleActions(),
-                                              pEvent->mimeData(), this);
+    CGuestDnDTarget dndTarget = guest.GetDnDTarget();
+
+    /* Ask the target for starting a DnD event. */
+    Qt::DropAction result = DnDHandler()->dragEnter(static_cast<CDnDTarget>(dndTarget),
+                                                    screenId(),
+                                                    frameBuffer()->convertHostXTo(cpnt.x()),
+                                                    frameBuffer()->convertHostYTo(cpnt.y()),
+                                                    pEvent->proposedAction(),
+                                                    pEvent->possibleActions(),
+                                                    pEvent->mimeData(), this /* pParent */);
 
     /* Set the DnD action returned by the guest. */
@@ -1182,18 +1188,20 @@
 void UIMachineView::dragMoveEvent(QDragMoveEvent *pEvent)
 {
-    /* The guest object to talk to. */
+    AssertPtrReturnVoid(pEvent);
+
+    /* Get mouse-pointer location. */
+    const QPoint &cpnt = viewportToContents(pEvent->pos());
+
     CGuest guest = session().GetConsole().GetGuest();
-
-    /* Get mouse-pointer location */
-    const QPoint &cpnt = viewportToContents(pEvent->pos());
+    CGuestDnDTarget dndTarget = guest.GetDnDTarget();
 
     /* Ask the guest for moving the drop cursor. */
-    Qt::DropAction result = gDnD->dragHGMove(guest,
-                                             screenId(),
-                                             frameBuffer()->convertHostXTo(cpnt.x()),
-                                             frameBuffer()->convertHostYTo(cpnt.y()),
-                                             pEvent->proposedAction(),
-                                             pEvent->possibleActions(),
-                                             pEvent->mimeData(), this);
+    Qt::DropAction result = DnDHandler()->dragMove(static_cast<CDnDTarget>(dndTarget),
+                                                   screenId(),
+                                                   frameBuffer()->convertHostXTo(cpnt.x()),
+                                                   frameBuffer()->convertHostYTo(cpnt.y()),
+                                                   pEvent->proposedAction(),
+                                                   pEvent->possibleActions(),
+                                                   pEvent->mimeData(), this /* pParent */);
 
     /* Set the DnD action returned by the guest. */
@@ -1204,28 +1212,47 @@
 void UIMachineView::dragLeaveEvent(QDragLeaveEvent *pEvent)
 {
-    /* The guest object to talk to. */
+    AssertPtrReturnVoid(pEvent);
+
     CGuest guest = session().GetConsole().GetGuest();
+    CGuestDnDTarget dndTarget = guest.GetDnDTarget();
 
     /* Ask the guest for stopping this DnD event. */
-    gDnD->dragHGLeave(guest, screenId(), this);
+    DnDHandler()->dragLeave(static_cast<CDnDTarget>(dndTarget),
+                            screenId(), this /* pParent */);
     pEvent->accept();
 }
 
+void UIMachineView::dragIsPending(void)
+{
+    /* At the moment we only support guest->host DnD. */
+    /** @todo Add guest->guest DnD functionality here by getting
+     *        the source of guest B (when copying from B to A). */
+    CGuest guest = session().GetConsole().GetGuest();
+    CDnDSource &dndSource = static_cast<CDnDSource>(guest.GetDnDSource());
+
+    /* Check for a pending DnD event within the guest and if so, handle all the
+     * magic. */
+    DnDHandler()->dragIsPending(session(), dndSource, screenId(), this /* pParent */);
+}
+
 void UIMachineView::dropEvent(QDropEvent *pEvent)
 {
-    /* The guest object to talk to. */
+    AssertPtrReturnVoid(pEvent);
+
+    /* Get mouse-pointer location. */
+    const QPoint &cpnt = viewportToContents(pEvent->pos());
+
     CGuest guest = session().GetConsole().GetGuest();
-
-    /* Get mouse-pointer location */
-    const QPoint &cpnt = viewportToContents(pEvent->pos());
+    CGuestDnDTarget dndTarget = guest.GetDnDTarget();
 
     /* Ask the guest for dropping data. */
-    Qt::DropAction result = gDnD->dragHGDrop(guest,
-                                             screenId(),
-                                             frameBuffer()->convertHostXTo(cpnt.x()),
-                                             frameBuffer()->convertHostYTo(cpnt.y()),
-                                             pEvent->proposedAction(),
-                                             pEvent->possibleActions(),
-                                             pEvent->mimeData(), this);
+    Qt::DropAction result = DnDHandler()->dragDrop(session(),
+                                                   static_cast<CDnDTarget>(dndTarget),
+                                                   screenId(),
+                                                   frameBuffer()->convertHostXTo(cpnt.x()),
+                                                   frameBuffer()->convertHostYTo(cpnt.y()),
+                                                   pEvent->proposedAction(),
+                                                   pEvent->possibleActions(),
+                                                   pEvent->mimeData(), this /* pParent */);
 
     /* Set the DnD action returned by the guest. */
@@ -1233,14 +1260,4 @@
     pEvent->accept();
 }
-
-void UIMachineView::handleGHDnd(void)
-{
-    /* The guest object to talk to. */
-    CGuest guest = session().GetConsole().GetGuest();
-
-    /* Check for a pending DnD event within the guest and if so, handle all the
-     * magic. */
-    gDnD->dragGHPending(session(), screenId(), this);
-}
 #endif /* VBOX_WITH_DRAG_AND_DROP */
 
@@ -1249,8 +1266,10 @@
 bool UIMachineView::winEvent(MSG *pMsg, long* /* piResult */)
 {
-    /* Check if some system event should be filtered-out.
-     * Returning 'true' means filtering-out,
-     * Returning 'false' means passing event to Qt. */
-    bool fResult = false; /* Pass to Qt by default: */
+    AssertPtrReturn(pMsg, false);
+
+    /* Check if some system event should be filtered out.
+     * Returning @c true means filtering-out,
+     * Returning @c false means passing event to Qt. */
+    bool fResult = false; /* Pass to Qt by default. */
     switch (pMsg->message)
     {
@@ -1260,7 +1279,8 @@
         case WM_SYSKEYUP:
         {
-            /* Filter using keyboard-filter: */
-            bool fKeyboardFilteringResult = machineLogic()->keyboardHandler()->winEventFilter(pMsg, screenId());
-            /* Keyboard filter rules the result: */
+            /* Filter using keyboard filter? */
+            bool fKeyboardFilteringResult =
+                machineLogic()->keyboardHandler()->winEventFilter(pMsg, screenId());
+            /* Keyboard filter rules the result? */
             fResult = fKeyboardFilteringResult;
             break;
@@ -1269,5 +1289,5 @@
             break;
     }
-    /* Return result: */
+
     return fResult;
 }
@@ -1277,8 +1297,10 @@
 bool UIMachineView::x11Event(XEvent *pEvent)
 {
-    /* Check if some system event should be filtered-out.
-     * Returning 'true' means filtering-out,
-     * Returning 'false' means passing event to Qt. */
-    bool fResult = false; /* Pass to Qt by default: */
+    AssertPtrReturn(pEvent, false);
+
+    /* Check if some system event should be filtered out.
+     * Returning @c true means filtering-out,
+     * Returning @c false means passing event to Qt. */
+    bool fResult = false; /* Pass to Qt by default. */
     switch (pEvent->type)
     {
@@ -1288,9 +1310,11 @@
         case XKeyRelease:
         {
-            /* Filter using keyboard-filter: */
-            bool fKeyboardFilteringResult = machineLogic()->keyboardHandler()->x11EventFilter(pEvent, screenId());
-            /* Filter using mouse-filter: */
-            bool fMouseFilteringResult = machineLogic()->mouseHandler()->x11EventFilter(pEvent, screenId());
-            /* If at least one of filters wants to filter event out then the result is 'true': */
+            /* Filter using keyboard-filter? */
+            bool fKeyboardFilteringResult =
+                machineLogic()->keyboardHandler()->x11EventFilter(pEvent, screenId());
+            /* Filter using mouse-filter? */
+            bool fMouseFilteringResult =
+                machineLogic()->mouseHandler()->x11EventFilter(pEvent, screenId());
+            /* If at least one of filters wants to filter event out then the result is true. */
             fResult = fKeyboardFilteringResult || fMouseFilteringResult;
             break;
@@ -1299,8 +1323,8 @@
             break;
     }
-    /* Return result: */
+
     return fResult;
 }
 
-#endif
-
+#endif /* Q_WS_X11 */
+
Index: trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineView.h
===================================================================
--- trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineView.h	(revision 51474)
+++ trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineView.h	(revision 51476)
@@ -39,4 +39,7 @@
 class UIMachineWindow;
 class UIFrameBuffer;
+#ifdef VBOX_WITH_DRAG_AND_DROP
+ class CDnDTarget;
+#endif
 class CSession;
 
@@ -217,7 +220,6 @@
     void dragLeaveEvent(QDragLeaveEvent *pEvent);
     void dragMoveEvent(QDragMoveEvent *pEvent);
+    void dragIsPending(void);
     void dropEvent(QDropEvent *pEvent);
-
-    void handleGHDnd();
 #endif /* VBOX_WITH_DRAG_AND_DROP */
 
Index: trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIMouseHandler.cpp
===================================================================
--- trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIMouseHandler.cpp	(revision 51474)
+++ trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIMouseHandler.cpp	(revision 51476)
@@ -7,5 +7,5 @@
 
 /*
- * Copyright (C) 2010-2012 Oracle Corporation
+ * Copyright (C) 2010-2014 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
@@ -936,9 +936,9 @@
                 || cpnt.y() > iCh - 1)
             {
-                bool fHandledGHDnD
+                bool fHandleDnDPending
                     = RT_BOOL(mouseButtons.testFlag(Qt::LeftButton));
-                if (fHandledGHDnD)
-                {
-                    m_views[uScreenId]->handleGHDnd();
+                if (fHandleDnDPending)
+                {
+                    m_views[uScreenId]->dragIsPending();
                     return true;
                 }
Index: trunk/src/VBox/Frontends/VirtualBox/src/settings/machine/UIMachineSettingsGeneral.cpp
===================================================================
--- trunk/src/VBox/Frontends/VirtualBox/src/settings/machine/UIMachineSettingsGeneral.cpp	(revision 51474)
+++ trunk/src/VBox/Frontends/VirtualBox/src/settings/machine/UIMachineSettingsGeneral.cpp	(revision 51476)
@@ -7,5 +7,5 @@
 
 /*
- * Copyright (C) 2006-2012 Oracle Corporation
+ * Copyright (C) 2006-2014 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
@@ -44,8 +44,8 @@
 
     /* Drag'n'drop mode */
-    mCbDragAndDrop->addItem (""); /* KDragAndDropMode_Disabled */
-    mCbDragAndDrop->addItem (""); /* KDragAndDropMode_HostToGuest */
-    mCbDragAndDrop->addItem (""); /* KDragAndDropMode_GuestToHost */
-    mCbDragAndDrop->addItem (""); /* KDragAndDropMode_Bidirectional */
+    mCbDragAndDrop->addItem (""); /* KDnDMode_Disabled */
+    mCbDragAndDrop->addItem (""); /* KDnDMode_HostToGuest */
+    mCbDragAndDrop->addItem (""); /* KDnDMode_GuestToHost */
+    mCbDragAndDrop->addItem (""); /* KDnDMode_Bidirectional */
 
 #ifdef Q_WS_MAC
@@ -115,5 +115,5 @@
     generalData.m_strSnapshotsHomeDir = QFileInfo(m_machine.GetSettingsFilePath()).absolutePath();
     generalData.m_clipboardMode = m_machine.GetClipboardMode();
-    generalData.m_dragAndDropMode = m_machine.GetDragAndDropMode();
+    generalData.m_dndMode = m_machine.GetDnDMode();
     generalData.m_strDescription = m_machine.GetDescription();
 
@@ -141,5 +141,5 @@
     mPsSnapshot->setHomeDir(generalData.m_strSnapshotsHomeDir);
     mCbClipboard->setCurrentIndex(generalData.m_clipboardMode);
-    mCbDragAndDrop->setCurrentIndex(generalData.m_dragAndDropMode);
+    mCbDragAndDrop->setCurrentIndex(generalData.m_dndMode);
     mTeDescription->setPlainText(generalData.m_strDescription);
 
@@ -166,5 +166,5 @@
     generalData.m_strSnapshotsFolder = mPsSnapshot->path();
     generalData.m_clipboardMode = (KClipboardMode)mCbClipboard->currentIndex();
-    generalData.m_dragAndDropMode = (KDragAndDropMode)mCbDragAndDrop->currentIndex();
+    generalData.m_dndMode = (KDnDMode)mCbDragAndDrop->currentIndex();
     generalData.m_strDescription = mTeDescription->toPlainText().isEmpty() ?
                                    QString::null : mTeDescription->toPlainText();
@@ -192,5 +192,5 @@
             /* Advanced tab: */
             m_machine.SetClipboardMode(generalData.m_clipboardMode);
-            m_machine.SetDragAndDropMode(generalData.m_dragAndDropMode);
+            m_machine.SetDnDMode(generalData.m_dndMode);
             m_machine.SetExtraData(GUI_SaveMountedAtRuntime, generalData.m_fSaveMountedAtRuntime ? "yes" : "no");
             m_machine.SetExtraData(GUI_ShowMiniToolBar, generalData.m_fShowMiniToolBar ? "yes" : "no");
@@ -292,8 +292,8 @@
 
     /* Drag'n'drop mode */
-    mCbDragAndDrop->setItemText (0, gpConverter->toString (KDragAndDropMode_Disabled));
-    mCbDragAndDrop->setItemText (1, gpConverter->toString (KDragAndDropMode_HostToGuest));
-    mCbDragAndDrop->setItemText (2, gpConverter->toString (KDragAndDropMode_GuestToHost));
-    mCbDragAndDrop->setItemText (3, gpConverter->toString (KDragAndDropMode_Bidirectional));
+    mCbDragAndDrop->setItemText (0, gpConverter->toString (KDnDMode_Disabled));
+    mCbDragAndDrop->setItemText (1, gpConverter->toString (KDnDMode_HostToGuest));
+    mCbDragAndDrop->setItemText (2, gpConverter->toString (KDnDMode_GuestToHost));
+    mCbDragAndDrop->setItemText (3, gpConverter->toString (KDnDMode_Bidirectional));
 }
 
Index: trunk/src/VBox/Frontends/VirtualBox/src/settings/machine/UIMachineSettingsGeneral.h
===================================================================
--- trunk/src/VBox/Frontends/VirtualBox/src/settings/machine/UIMachineSettingsGeneral.h	(revision 51474)
+++ trunk/src/VBox/Frontends/VirtualBox/src/settings/machine/UIMachineSettingsGeneral.h	(revision 51476)
@@ -6,5 +6,5 @@
 
 /*
- * Copyright (C) 2006-2012 Oracle Corporation
+ * Copyright (C) 2006-2014 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
@@ -37,5 +37,5 @@
         , m_strSnapshotsHomeDir(QString())
         , m_clipboardMode(KClipboardMode_Disabled)
-        , m_dragAndDropMode(KDragAndDropMode_Disabled)
+        , m_dndMode(KDnDMode_Disabled)
         , m_strDescription(QString()) {}
     /* Functions: */
@@ -50,5 +50,5 @@
                (m_strSnapshotsHomeDir == other.m_strSnapshotsHomeDir) &&
                (m_clipboardMode == other.m_clipboardMode) &&
-               (m_dragAndDropMode == other.m_dragAndDropMode) &&
+               (m_dndMode == other.m_dndMode) &&
                (m_strDescription == other.m_strDescription);
     }
@@ -65,5 +65,5 @@
     QString m_strSnapshotsHomeDir;
     KClipboardMode m_clipboardMode;
-    KDragAndDropMode m_dragAndDropMode;
+    KDnDMode m_dndMode;
     QString m_strDescription;
 };
Index: trunk/src/VBox/Main/Makefile.kmk
===================================================================
--- trunk/src/VBox/Main/Makefile.kmk	(revision 51474)
+++ trunk/src/VBox/Main/Makefile.kmk	(revision 51476)
@@ -747,5 +747,7 @@
 ifdef VBOX_WITH_DRAG_AND_DROP
  VBoxC_SOURCES += \
-	src-client/GuestDnDImpl.cpp
+	src-client/GuestDnDPrivate.cpp \
+	src-client/GuestDnDSourceImpl.cpp \
+	src-client/GuestDnDTargetImpl.cpp
 endif
 ifdef VBOX_WITH_XPCOM
Index: trunk/src/VBox/Main/idl/VirtualBox.xidl
===================================================================
--- trunk/src/VBox/Main/idl/VirtualBox.xidl	(revision 51474)
+++ trunk/src/VBox/Main/idl/VirtualBox.xidl	(revision 51476)
@@ -1175,6 +1175,6 @@
 
   <enum
-    name="DragAndDropMode"
-    uuid="b618ea0e-b6fb-4f8d-97f7-5e237e49b547"
+    name="DnDMode"
+    uuid="07af8800-f936-4b33-9172-cd400e83c148"
     >
     <desc>
@@ -4204,5 +4204,5 @@
   <interface
     name="IMachine" extends="$unknown"
-    uuid="480cf695-2d8d-4256-9c7c-cce4184fa048"
+    uuid="45b0357d-28f4-4f90-b02c-13f2940efdda"
     wsmap="managed"
     wrap-hint-server-addinterfaces="IInternalMachineControl"
@@ -4790,7 +4790,7 @@
     </attribute>
 
-    <attribute name="dragAndDropMode" type="DragAndDropMode">
-      <desc>
-        Which mode is allowed for drag'n'drop.
+    <attribute name="dnDMode" type="DnDMode">
+      <desc>
+        Sets or retrieves the current drag'n drop mode.
       </desc>
     </attribute>
@@ -10351,9 +10351,9 @@
 
   <enum
-    name="DragAndDropAction"
-    uuid="47f3b162-c107-4fcd-bfa7-54b8135c441e"
+    name="DnDAction"
+    uuid="17609e74-778e-4d0e-8827-35f5230f287b"
   >
     <desc>
-      Possible actions within an Drag and Drop operation.
+      Possible actions of a drag'n drop operation.
     </desc>
 
@@ -10389,4 +10389,238 @@
     </const>
   </enum>
+
+  <interface
+    name="IDnDSource" extends="$unknown"
+    uuid="6bdc3f97-f6df-4357-b252-5fa16e0c1e24"
+    wsmap="managed"
+    >
+    <desc>Abstract interface for handling drag'n drop sources.</desc>
+
+    <method name="dragIsPending">
+      <desc>
+        Ask the source if there is any drag and drop operation pending.
+        If no drag and drop operation is pending currently, DnDAction_Ignore is returned.
+
+        <result name="VBOX_E_VM_ERROR">
+          VMM device is not available.
+        </result>
+      </desc>
+      <param name="screenId" type="unsigned long" dir="in">
+        <desc>The screen ID where the drag and drop event occurred.</desc>
+      </param>
+      <param name="formats" type="wstring" dir="out" safearray="yes">
+        <desc>On return the supported mime types.</desc>
+      </param>
+      <param name="allowedActions" type="DnDAction" dir="out" safearray="yes">
+        <desc>On return the actions which are allowed.</desc>
+      </param>
+      <param name="defaultAction" type="DnDAction" dir="return">
+        <desc>On return the default action to use.</desc>
+      </param>
+    </method>
+
+    <method name="drop">
+      <desc>
+        Informs the source that a drop event occurred for a pending
+        drag and drop operation.
+
+        <result name="VBOX_E_VM_ERROR">
+          VMM device is not available.
+        </result>
+      </desc>
+
+      <param name="format" type="wstring" dir="in">
+        <desc>The mime type the data must be in.</desc>
+      </param>
+      <param name="action" type="DnDAction" dir="in">
+        <desc>The action to use.</desc>
+      </param>
+      <param name="progress" type="IProgress" dir="return">
+        <desc>Progress object to track the operation completion.</desc>
+      </param>
+    </method>
+
+    <method name="receiveData">
+      <desc>
+        Receive the data of a previously drag and drop event from the source.
+
+        <result name="VBOX_E_VM_ERROR">
+          VMM device is not available.
+        </result>
+
+      </desc>
+
+      <param name="data" type="octet" safearray="yes" dir="return">
+        <desc>The actual data.</desc>
+      </param>
+    </method>
+
+  </interface>
+
+  <interface
+    name="IGuestDnDSource" extends="IDnDSource"
+    uuid="280955c0-de67-4297-8179-6274a82a2fc0"
+    wsmap="managed"
+    >
+
+    <desc>
+      Implementation of the <link to="IDnDSource" /> object
+      for source drag'n drop operations on the guest.
+    </desc>
+  </interface>
+
+  <interface
+    name="IDnDTarget" extends="$unknown"
+    uuid="50862c12-7618-4542-a7c7-6a21de2644f7"
+    wsmap="managed"
+    >
+    <desc>Abstract interface for handling drag'n drop targets.</desc>
+
+    <method name="enter">
+      <desc>
+        Informs the target about a drag and drop enter event.
+
+        <result name="VBOX_E_VM_ERROR">
+          VMM device is not available.
+        </result>
+      </desc>
+      <param name="screenId" type="unsigned long" dir="in">
+        <desc>The screen ID where the drag and drop event occurred.</desc>
+      </param>
+      <param name="y" type="unsigned long" dir="in">
+        <desc>Y-position of the event.</desc>
+      </param>
+      <param name="x" type="unsigned long" dir="in">
+        <desc>X-position of the event.</desc>
+      </param>
+      <param name="defaultAction" type="DnDAction" dir="in">
+        <desc>The default action to use.</desc>
+      </param>
+      <param name="allowedActions" type="DnDAction" dir="in" safearray="yes">
+        <desc>The actions which are allowed.</desc>
+      </param>
+      <param name="formats" type="wstring" dir="in" safearray="yes">
+        <desc>The supported MIME types.</desc>
+      </param>
+      <param name="resultAction" type="DnDAction" dir="return">
+        <desc>The resulting action of this event.</desc>
+      </param>
+    </method>
+
+    <method name="move">
+      <desc>
+        Informs the target about a drag and drop move event.
+
+        <result name="VBOX_E_VM_ERROR">
+          VMM device is not available.
+        </result>
+      </desc>
+      <param name="screenId" type="unsigned long" dir="in">
+        <desc>The screen ID where the drag and drop event occurred.</desc>
+      </param>
+      <param name="x" type="unsigned long" dir="in">
+        <desc>X-position of the event.</desc>
+      </param>
+      <param name="y" type="unsigned long" dir="in">
+        <desc>Y-position of the event.</desc>
+      </param>
+      <param name="defaultAction" type="DnDAction" dir="in">
+        <desc>The default action to use.</desc>
+      </param>
+      <param name="allowedActions" type="DnDAction" dir="in" safearray="yes">
+        <desc>The actions which are allowed.</desc>
+      </param>
+      <param name="formats" type="wstring" dir="in" safearray="yes">
+        <desc>The supported MIME types.</desc>
+      </param>
+      <param name="resultAction" type="DnDAction" dir="return">
+        <desc>The resulting action of this event.</desc>
+      </param>
+    </method>
+
+    <method name="leave">
+      <desc>
+        Informs the target about a drag and drop leave event.
+
+        <result name="VBOX_E_VM_ERROR">
+          VMM device is not available.
+        </result>
+      </desc>
+      <param name="screenId" type="unsigned long" dir="in">
+        <desc>The screen ID where the drag and drop event occurred.</desc>
+      </param>
+    </method>
+
+    <method name="drop">
+      <desc>
+        Informs the target about a drop event.
+
+        <result name="VBOX_E_VM_ERROR">
+          VMM device is not available.
+        </result>
+
+      </desc>
+      <param name="screenId" type="unsigned long" dir="in">
+        <desc>The screen ID where the Drag and Drop event occurred.</desc>
+      </param>
+      <param name="x" type="unsigned long" dir="in">
+        <desc>X-position of the event.</desc>
+      </param>
+      <param name="y" type="unsigned long" dir="in">
+        <desc>Y-position of the event.</desc>
+      </param>
+      <param name="defaultAction" type="DnDAction" dir="in">
+        <desc>The default action to use.</desc>
+      </param>
+      <param name="allowedActions" type="DnDAction" dir="in" safearray="yes">
+        <desc>The actions which are allowed.</desc>
+      </param>
+      <param name="formats" type="wstring" dir="in" safearray="yes">
+        <desc>The supported MIME types.</desc>
+      </param>
+      <param name="format" type="wstring" dir="out">
+        <desc>The resulting format of this event.</desc>
+      </param>
+      <param name="resultAction" type="DnDAction" dir="return">
+        <desc>The resulting action of this event.</desc>
+      </param>
+    </method>
+
+    <method name="sendData">
+      <desc>
+        Sends data to the target.
+
+        <result name="VBOX_E_VM_ERROR">
+          VMM device is not available.
+        </result>
+
+      </desc>
+      <param name="screenId" type="unsigned long" dir="in">
+        <desc>The screen ID where the drag and drop event occurred.</desc>
+      </param>
+      <param name="format" type="wstring" dir="in">
+        <desc>The MIME type the data is in.</desc>
+      </param>
+      <param name="data" type="octet" dir="in" safearray="yes">
+        <desc>The actual data.</desc>
+      </param>
+      <param name="progress" type="IProgress" dir="return">
+        <desc>Progress object to track the operation completion.</desc>
+      </param>
+    </method>
+
+  </interface>
+
+  <interface
+    name="IGuestDnDTarget" extends="IDnDTarget"
+    uuid="50ce4b51-0ff7-46b7-a138-3c6e5ac946b4"
+    wsmap="managed"
+    >
+
+    <desc>
+      Implementation of the <link to="IDnDTarget" /> object
+      for target drag'n drop operations on the guest.
+    </desc>
+  </interface>
 
   <interface
@@ -11882,5 +12116,5 @@
   <interface
     name="IGuest" extends="$unknown"
-    uuid="8011a1b1-6adb-4ffb-a37e-20abdaee4650"
+    uuid="97927199-7e1f-4094-97ab-92333e727843"
     wsmap="managed"
     >
@@ -11930,4 +12164,16 @@
     </attribute>
 
+    <attribute name="dnDSource" type="IGuestDnDSource" readonly="yes">
+      <desc>
+        TODO
+      </desc>
+    </attribute>
+
+    <attribute name="dnDTarget" type="IGuestDnDTarget" readonly="yes">
+      <desc>
+        TODO
+      </desc>
+    </attribute>
+
     <attribute name="eventSource" type="IEventSource" readonly="yes">
       <desc>
@@ -12060,217 +12306,4 @@
           not be supported by all versions of the Additions.
         </desc>
-      </param>
-    </method>
-
-    <method name="dragHGEnter">
-      <desc>
-        Informs the guest about a Drag and Drop enter event.
-
-        This is used in Host - Guest direction.
-
-        <result name="VBOX_E_VM_ERROR">
-          VMM device is not available.
-        </result>
-
-      </desc>
-      <param name="screenId" type="unsigned long" dir="in">
-        <desc>The screen id where the Drag and Drop event occurred.</desc>
-      </param>
-      <param name="y" type="unsigned long" dir="in">
-        <desc>y-position of the event.</desc>
-      </param>
-      <param name="x" type="unsigned long" dir="in">
-        <desc>x-position of the event.</desc>
-      </param>
-      <param name="defaultAction" type="DragAndDropAction" dir="in">
-        <desc>The default action to use.</desc>
-      </param>
-      <param name="allowedActions" type="DragAndDropAction" dir="in" safearray="yes">
-        <desc>The actions which are allowed.</desc>
-      </param>
-      <param name="formats" type="wstring" dir="in" safearray="yes">
-        <desc>The supported mime types.</desc>
-      </param>
-      <param name="resultAction" type="DragAndDropAction" dir="return">
-        <desc>The resulting action of this event.</desc>
-      </param>
-    </method>
-
-    <method name="dragHGMove">
-      <desc>
-        Informs the guest about a Drag and Drop move event.
-
-        This is used in Host - Guest direction.
-
-        <result name="VBOX_E_VM_ERROR">
-          VMM device is not available.
-        </result>
-
-      </desc>
-      <param name="screenId" type="unsigned long" dir="in">
-        <desc>The screen id where the Drag and Drop event occurred.</desc>
-      </param>
-      <param name="x" type="unsigned long" dir="in">
-        <desc>x-position of the event.</desc>
-      </param>
-      <param name="y" type="unsigned long" dir="in">
-        <desc>y-position of the event.</desc>
-      </param>
-      <param name="defaultAction" type="DragAndDropAction" dir="in">
-        <desc>The default action to use.</desc>
-      </param>
-      <param name="allowedActions" type="DragAndDropAction" dir="in" safearray="yes">
-        <desc>The actions which are allowed.</desc>
-      </param>
-      <param name="formats" type="wstring" dir="in" safearray="yes">
-        <desc>The supported mime types.</desc>
-      </param>
-      <param name="resultAction" type="DragAndDropAction" dir="return">
-        <desc>The resulting action of this event.</desc>
-      </param>
-    </method>
-
-    <method name="dragHGLeave">
-      <desc>
-        Informs the guest about a Drag and Drop leave event.
-
-        This is used in Host - Guest direction.
-
-        <result name="VBOX_E_VM_ERROR">
-          VMM device is not available.
-        </result>
-
-      </desc>
-      <param name="screenId" type="unsigned long" dir="in">
-        <desc>The screen id where the Drag and Drop event occurred.</desc>
-      </param>
-    </method>
-
-    <method name="dragHGDrop">
-      <desc>
-        Informs the guest about a drop event.
-
-        This is used in Host - Guest direction.
-
-        <result name="VBOX_E_VM_ERROR">
-          VMM device is not available.
-        </result>
-
-      </desc>
-      <param name="screenId" type="unsigned long" dir="in">
-        <desc>The screen id where the Drag and Drop event occurred.</desc>
-      </param>
-      <param name="x" type="unsigned long" dir="in">
-        <desc>x-position of the event.</desc>
-      </param>
-      <param name="y" type="unsigned long" dir="in">
-        <desc>y-position of the event.</desc>
-      </param>
-      <param name="defaultAction" type="DragAndDropAction" dir="in">
-        <desc>The default action to use.</desc>
-      </param>
-      <param name="allowedActions" type="DragAndDropAction" dir="in" safearray="yes">
-        <desc>The actions which are allowed.</desc>
-      </param>
-      <param name="formats" type="wstring" dir="in" safearray="yes">
-        <desc>The supported mime types.</desc>
-      </param>
-      <param name="format" type="wstring" dir="out">
-        <desc>The resulting format of this event.</desc>
-      </param>
-      <param name="resultAction" type="DragAndDropAction" dir="return">
-        <desc>The resulting action of this event.</desc>
-      </param>
-    </method>
-
-    <method name="dragHGPutData">
-      <desc>
-        Informs the guest about a drop data event.
-
-        This is used in Host - Guest direction.
-
-        <result name="VBOX_E_VM_ERROR">
-          VMM device is not available.
-        </result>
-
-      </desc>
-      <param name="screenId" type="unsigned long" dir="in">
-        <desc>The screen id where the Drag and Drop event occurred.</desc>
-      </param>
-      <param name="format" type="wstring" dir="in">
-        <desc>The mime type the data is in.</desc>
-      </param>
-      <param name="data" type="octet" dir="in" safearray="yes">
-        <desc>The actual data.</desc>
-      </param>
-      <param name="progress" type="IProgress" dir="return">
-        <desc>Progress object to track the operation completion.</desc>
-      </param>
-    </method>
-
-    <method name="dragGHPending">
-      <desc>
-        Ask the guest if there is any Drag and Drop operation pending in the guest.
-
-        If no Drag and Drop operation is pending currently, Ignore is returned.
-
-        This is used in Guest - Host direction.
-
-        <result name="VBOX_E_VM_ERROR">
-          VMM device is not available.
-        </result>
-
-      </desc>
-      <param name="screenId" type="unsigned long" dir="in">
-        <desc>The screen id where the Drag and Drop event occurred.</desc>
-      </param>
-      <param name="formats" type="wstring" dir="out" safearray="yes">
-        <desc>On return the supported mime types.</desc>
-      </param>
-      <param name="allowedActions" type="DragAndDropAction" dir="out" safearray="yes">
-        <desc>On return the actions which are allowed.</desc>
-      </param>
-      <param name="defaultAction" type="DragAndDropAction" dir="return">
-        <desc>On return the default action to use.</desc>
-      </param>
-    </method>
-
-    <method name="dragGHDropped">
-      <desc>
-        Informs the guest that a drop event occurred for a pending Drag and Drop event.
-
-        This is used in Guest - Host direction.
-
-        <result name="VBOX_E_VM_ERROR">
-          VMM device is not available.
-        </result>
-
-      </desc>
-
-      <param name="format" type="wstring" dir="in">
-        <desc>The mime type the data must be in.</desc>
-      </param>
-      <param name="action" type="DragAndDropAction" dir="in">
-        <desc>The action to use.</desc>
-      </param>
-      <param name="progress" type="IProgress" dir="return">
-        <desc>Progress object to track the operation completion.</desc>
-      </param>
-    </method>
-
-    <method name="dragGHGetData">
-      <desc>
-        Fetch the data of a previously Drag and Drop event from the guest.
-
-        This is used in Guest - Host direction.
-
-        <result name="VBOX_E_VM_ERROR">
-          VMM device is not available.
-        </result>
-
-      </desc>
-
-      <param name="data" type="octet" safearray="yes" dir="return">
-        <desc>The actual data.</desc>
       </param>
     </method>
@@ -15600,5 +15633,12 @@
 
     <method name="getScreenResolution">
-      <desc>Queries display width, height and color depth for given screen.</desc>
+      <desc>
+        Queries certain attributes such as display width, height, color depth
+        and the X and Y origin for a given guest screen.
+
+        The parameters @a xOrigin and @a yOrigin return the X and Y
+        coordinates of the framebuffer's origin.
+
+        All return parameters are optional.</desc>
       <param name="screenId" type="unsigned long" dir="in"/>
       <param name="width" type="unsigned long" dir="out"/>
@@ -15611,5 +15651,5 @@
     <method name="attachFramebuffer">
       <desc>
-        Sets the graphics updates target for a screen.
+        Sets the graphics update target for a screen.
       </desc>
       <param name="screenId" type="unsigned long" dir="in"/>
@@ -18013,10 +18053,10 @@
     </method>
 
-    <method name="onDragAndDropModeChange">
-      <desc>
-        Notification when the drag'n'drop mode changes.
-      </desc>
-      <param name="dragAndDropMode" type="DragAndDropMode" dir="in">
-        <desc>The new mode for drag'n'drop.</desc>
+    <method name="onDnDModeChange">
+      <desc>
+        Notification when the drag'n drop mode changes.
+      </desc>
+      <param name="dndMode" type="DnDMode" dir="in">
+        <desc>The new mode for drag'n drop.</desc>
       </param>
     </method>
@@ -19806,5 +19846,5 @@
   <enum
     name="VBoxEventType"
-    uuid="5248e377-e578-47d7-b07b-84b1db6db8a8"
+    uuid="1622f8d2-6c76-4410-9e78-86e083046efc"
     >
 
@@ -20069,7 +20109,7 @@
       </desc>
     </const>
-    <const name="OnDragAndDropModeChanged" value="73">
-      <desc>
-        See <link to="IDragAndDropModeChangedEvent">IDragAndDropModeChangedEvent</link>.
+    <const name="OnDnDModeChanged" value="73">
+      <desc>
+        See <link to="IDnDModeChangedEvent">IDnDModeChangedEvent</link>.
       </desc>
     </const>
@@ -20958,14 +20998,14 @@
 
   <interface
-    name="IDragAndDropModeChangedEvent" extends="IEvent"
-    uuid="e90b8850-ac8e-4dff-8059-4100ae2c3c3d"
-    wsmap="managed" autogen="VBoxEvent" id="OnDragAndDropModeChanged"
+    name="IDnDModeChangedEvent" extends="IEvent"
+    uuid="b55cf856-1f8b-4692-abb4-462429fae5e9"
+    wsmap="managed" autogen="VBoxEvent" id="OnDnDModeChanged"
     >
     <desc>
-      Notification when the drag'n'drop mode changes.
+      Notification when the drag'n drop mode changes.
     </desc>
-    <attribute name="dragAndDropMode" type="DragAndDropMode" readonly="yes">
-      <desc>
-        The new drag'n'drop mode.
+    <attribute name="dndMode" type="DnDMode" readonly="yes">
+      <desc>
+        The new drag'n drop mode.
       </desc>
     </attribute>
Index: trunk/src/VBox/Main/include/ConsoleImpl.h
===================================================================
--- trunk/src/VBox/Main/include/ConsoleImpl.h	(revision 51474)
+++ trunk/src/VBox/Main/include/ConsoleImpl.h	(revision 51476)
@@ -220,5 +220,5 @@
     HRESULT onCPUExecutionCapChange(ULONG aExecutionCap);
     HRESULT onClipboardModeChange(ClipboardMode_T aClipboardMode);
-    HRESULT onDragAndDropModeChange(DragAndDropMode_T aDragAndDropMode);
+    HRESULT onDnDModeChange(DnDMode_T aDnDMode);
     HRESULT onVRDEServerChange(BOOL aRestart);
     HRESULT onVideoCaptureChange();
@@ -699,5 +699,5 @@
 
     void changeClipboardMode(ClipboardMode_T aClipboardMode);
-    void changeDragAndDropMode(DragAndDropMode_T aDragAndDropMode);
+    int changeDnDMode(DnDMode_T aDnDMode);
 
 #ifdef VBOX_WITH_USB
Index: trunk/src/VBox/Main/include/DisplayImpl.h
===================================================================
--- trunk/src/VBox/Main/include/DisplayImpl.h	(revision 51474)
+++ trunk/src/VBox/Main/include/DisplayImpl.h	(revision 51476)
@@ -5,5 +5,5 @@
 
 /*
- * Copyright (C) 2006-2013 Oracle Corporation
+ * Copyright (C) 2006-2014 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
@@ -66,5 +66,5 @@
     uint16_t flags;
 
-    /* for saving the rectangles arrived during fb resize is in progress. */
+    /** For saving the rectangles arrived during fb resize is in progress. */
     PRTRECT mpSavedVisibleRegion;
     uint32_t mcSavedVisibleRegion;
@@ -74,5 +74,5 @@
     volatile uint32_t u32ResizeStatus;
 
-    /* The Framebuffer has default format and must be updates immediately. */
+    /** The framebuffer has default format and must be updates immediately. */
     bool fDefaultFormat;
 
Index: trunk/src/VBox/Main/include/GuestDnDImpl.h
===================================================================
--- trunk/src/VBox/Main/include/GuestDnDImpl.h	(revision 51474)
+++ 	(revision )
@@ -1,64 +1,0 @@
-/** @file
- * Definition of GuestDnD
- */
-
-/*
- * Copyright (C) 2011-2014 Oracle Corporation
- *
- * This file is part of VirtualBox Open Source Edition (OSE), as
- * available from http://www.virtualbox.org. This file is free software;
- * you can redistribute it and/or modify it under the terms of the GNU
- * General Public License (GPL) as published by the Free Software
- * Foundation, in version 2 as it comes in the "COPYING" file of the
- * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
- * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
- */
-
-#ifndef ____H_GUESTDND
-#define ____H_GUESTDND
-
-/* Forward declaration of the d-pointer. */
-class GuestDnDPrivate;
-#ifdef VBOX_WITH_DRAG_AND_DROP_GH
- class DnDGuestResponse;
-#endif
-
-class GuestDnD
-{
-public:
-    GuestDnD(const ComObjPtr<Guest>& pGuest);
-    ~GuestDnD();
-
-    /* Host -> Guest */
-    HRESULT dragHGEnter(ULONG uScreenId, ULONG uX, ULONG uY, DragAndDropAction_T defaultAction, ComSafeArrayIn(DragAndDropAction_T, allowedActions), ComSafeArrayIn(IN_BSTR, formats), DragAndDropAction_T *pResultAction);
-    HRESULT dragHGMove(ULONG uScreenId, ULONG uX, ULONG uY, DragAndDropAction_T defaultAction, ComSafeArrayIn(DragAndDropAction_T, allowedActions), ComSafeArrayIn(IN_BSTR, formats), DragAndDropAction_T *pResultAction);
-    HRESULT dragHGLeave(ULONG uScreenId);
-    HRESULT dragHGDrop(ULONG uScreenId, ULONG uX, ULONG uY, DragAndDropAction_T defaultAction, ComSafeArrayIn(DragAndDropAction_T, allowedActions), ComSafeArrayIn(IN_BSTR, formats), BSTR *pstrFormat, DragAndDropAction_T *pResultAction);
-    HRESULT dragHGPutData(ULONG uScreenId, IN_BSTR wstrFormat, ComSafeArrayIn(BYTE, data), IProgress **ppProgress);
-
-    /* Guest -> Host */
-    HRESULT dragGHPending(ULONG uScreenId, ComSafeArrayOut(BSTR, formats), ComSafeArrayOut(DragAndDropAction_T, allowedActions), DragAndDropAction_T *pDefaultAction);
-    HRESULT dragGHDropped(IN_BSTR bstrFormat, DragAndDropAction_T action, IProgress **ppProgress);
-    HRESULT dragGHGetData(ComSafeArrayOut(BYTE, data));
-
-    /* Guest response */
-    static DECLCALLBACK(int) notifyGuestDragAndDropEvent(void *pvExtension, uint32_t u32Function, void *pvParms, uint32_t cbParms);
-
-protected:
-
-#ifdef VBOX_WITH_DRAG_AND_DROP_GH
-    int onGHSendData(DnDGuestResponse *pResp, const void *pvData, size_t cbData, size_t cbTotalSize);
-    int onGHSendDir(DnDGuestResponse *pResp, const char *pszPath, size_t cbPath, uint32_t fMode);
-    int onGHSendFile(DnDGuestResponse *pResp, const char *pszPath, size_t cbPath, void *pvData, size_t cbData, uint32_t fMode);
-#endif /* VBOX_WITH_DRAG_AND_DROP_GH */
-
-private:
-
-    /* d-pointer */
-    GuestDnDPrivate *d_ptr;
-
-    friend class GuestDnDPrivate;
-};
-
-#endif /* ____H_GUESTDND */
-
Index: trunk/src/VBox/Main/include/GuestDnDPrivate.h
===================================================================
--- trunk/src/VBox/Main/include/GuestDnDPrivate.h	(revision 51476)
+++ trunk/src/VBox/Main/include/GuestDnDPrivate.h	(revision 51476)
@@ -0,0 +1,195 @@
+/* $Id$ */
+/** @file
+ * Private guest drag and drop code, used by GuestDnDTarget +
+ * GuestDnDSource.
+ */
+
+/*
+ * Copyright (C) 2011-2014 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+#ifndef ____H_GUESTDNDPRIVATE
+#define ____H_GUESTDNDPRIVATE
+
+#include "VBox/hgcmsvc.h" /* For PVBOXHGCMSVCPARM. */
+
+/* Forward prototype declarations. */
+class Guest;
+class Progress;
+
+/**
+ * Class for handling drag'n drop responses from
+ * the guest side.
+ */
+class GuestDnDResponse
+{
+
+public:
+
+    GuestDnDResponse(const ComObjPtr<Guest>& pGuest);
+
+    virtual ~GuestDnDResponse(void);
+
+public:
+
+    int notifyAboutGuestResponse(void);
+    int waitForGuestResponse(RTMSINTERVAL msTimeout = 500);
+
+    void setDefAction(uint32_t a) { m_defAction = a; }
+    uint32_t defAction(void) const { return m_defAction; }
+
+    void setAllActions(uint32_t a) { m_allActions = a; }
+    uint32_t allActions() const { return m_allActions; }
+
+    void setFormat(const Utf8Str &strFormat) { m_strFormat = strFormat; }
+    Utf8Str format(void) const { return m_strFormat; }
+
+    void setDropDir(const Utf8Str &strDropDir) { m_strDropDir = strDropDir; }
+    Utf8Str dropDir(void) const { return m_strDropDir; }
+
+    int dataAdd(const void *pvData, uint32_t cbData, uint32_t *pcbCurSize);
+    int dataSetStatus(size_t cbDataAdd, size_t cbDataTotal = 0);
+    void reset(void);
+    const void *data(void) { return m_pvData; }
+    size_t size(void) const { return m_cbData; }
+
+    int setProgress(unsigned uPercentage, uint32_t uState, int rcOp = VINF_SUCCESS);
+    HRESULT resetProgress(const ComObjPtr<Guest>& pParent);
+    HRESULT queryProgressTo(IProgress **ppProgress);
+
+    int writeToFile(const char *pszPath, size_t cbPath, void *pvData, size_t cbData, uint32_t fMode);
+
+public:
+
+    Utf8Str errorToString(const ComObjPtr<Guest>& pGuest, int guestRc);
+
+private:
+    RTSEMEVENT           m_EventSem;
+    uint32_t             m_defAction;
+    uint32_t             m_allActions;
+    Utf8Str              m_strFormat;
+
+    /** The actual MIME data.*/
+    void                *m_pvData;
+    /** Size (in bytes) of MIME data. */
+    uint32_t             m_cbData;
+
+    size_t               m_cbDataCurrent;
+    size_t               m_cbDataTotal;
+    /** Dropped files directory on the host. */
+    Utf8Str              m_strDropDir;
+    /** The handle of the currently opened file being written to
+     *  or read from. */
+    RTFILE               m_hFile;
+    Utf8Str              m_strFile;
+
+    ComObjPtr<Guest>     m_parent;
+    ComObjPtr<Progress>  m_progress;
+};
+
+/**
+ * Private singleton class for the guest's DnD
+ * implementation. Can't be instanciated directly, only via
+ * the factory pattern.
+ */
+class GuestDnD
+{
+public:
+
+    static GuestDnD *createInstance(const ComObjPtr<Guest>& pGuest)
+    {
+        Assert(NULL == GuestDnD::s_pInstance);
+        GuestDnD::s_pInstance = new GuestDnD(pGuest);
+        return GuestDnD::s_pInstance;
+    }
+
+    static void destroyInstance(void)
+    {
+        if (GuestDnD::s_pInstance)
+        {
+            delete GuestDnD::s_pInstance;
+            GuestDnD::s_pInstance = NULL;
+        }
+    }
+
+    static inline GuestDnD *getInstance(void)
+    {
+        AssertPtr(GuestDnD::s_pInstance);
+        return GuestDnD::s_pInstance;
+    }
+
+protected:
+
+    GuestDnD(const ComObjPtr<Guest>& pGuest);
+    virtual ~GuestDnD(void);
+
+public:
+
+    /** @name Public helper functions.
+     * @{ */
+    int                        adjustScreenCoordinates(ULONG uScreenId, ULONG *puX, ULONG *puY) const;
+    int                        hostCall(uint32_t u32Function, uint32_t cParms, PVBOXHGCMSVCPARM paParms) const;
+    GuestDnDResponse          *response(void) { return m_pResponse; }
+    std::vector<com::Utf8Str>  supportedFormats(void) const { return m_strSupportedFormats; }
+    /** @}  */
+
+public:
+
+    /** @name Static low-level HGCM callback handler.
+     * @{ */
+    static DECLCALLBACK(int)   notifyDnDDispatcher(void *pvExtension, uint32_t u32Function, void *pvParms, uint32_t cbParms);
+    /** @}  */
+
+    /** @name Static helper methods.
+     * @{ */
+    static com::Utf8Str        toFormatString(const std::vector<com::Utf8Str> &lstSupportedFormats, const std::vector<com::Utf8Str> &lstFormats);
+    static void                toFormatVector(const std::vector<com::Utf8Str> &lstSupportedFormats, const com::Utf8Str &strFormats, std::vector<com::Utf8Str> &vecformats);
+    static DnDAction_T         toMainAction(uint32_t uAction);
+    static void                toMainActions(uint32_t uActions, std::vector<DnDAction_T> &vecActions);
+    static uint32_t            toHGCMAction(DnDAction_T enmAction);
+    static void                toHGCMActions(DnDAction_T enmDefAction, uint32_t *puDefAction, const std::vector<DnDAction_T> vecAllowedActions, uint32_t *puAllowedActions);
+    /** @}  */
+
+protected:
+
+    /** @name Singleton properties.
+     * @{ */
+    /** List of supported MIME types (formats). */
+    std::vector<com::Utf8Str>  m_strSupportedFormats;
+    /** Pointer to guest implementation. */
+    const ComObjPtr<Guest>     m_pGuest;
+    /** The current (last) response from the guest. At the
+     *  moment we only support only response a time (ARQ-style). */
+    GuestDnDResponse          *m_pResponse;
+    /** @}  */
+
+protected:
+
+#ifdef VBOX_WITH_DRAG_AND_DROP_GH
+    /** @name Dispatch handlers for the HGCM callbacks.
+     * @{ */
+    int onGHSendData(GuestDnDResponse *pResp, const void *pvData, size_t cbData, size_t cbTotalSize);
+    int onGHSendDir(GuestDnDResponse *pResp, const char *pszPath, size_t cbPath, uint32_t fMode);
+    int onGHSendFile(GuestDnDResponse *pResp, const char *pszPath, size_t cbPath, void *pvData, size_t cbData, uint32_t fMode);
+    /** @}  */
+#endif /* VBOX_WITH_DRAG_AND_DROP_GH */
+
+private:
+
+    /** Staic pointer to singleton instance. */
+    static GuestDnD           *s_pInstance;
+};
+
+/** Access to the GuestDnD's singleton instance. */
+#define GuestDnDInst() GuestDnD::getInstance()
+
+#endif /* ____H_GUESTDNDPRIVATE */
+
Index: trunk/src/VBox/Main/include/GuestDnDSourceImpl.h
===================================================================
--- trunk/src/VBox/Main/include/GuestDnDSourceImpl.h	(revision 51476)
+++ trunk/src/VBox/Main/include/GuestDnDSourceImpl.h	(revision 51476)
@@ -0,0 +1,58 @@
+/* $Id$ */
+/** @file
+ * VBox Console COM Class implementation - Guest drag'n drop source.
+ */
+
+/*
+ * Copyright (C) 2014 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+#ifndef ____H_GUESTDNDSOURCEIMPL
+#define ____H_GUESTDNDSOURCEIMPL
+
+#include "GuestDnDSourceWrap.h"
+#include "GuestDnDPrivate.h"
+
+class ATL_NO_VTABLE GuestDnDSource :
+    public GuestDnDSourceWrap
+{
+public:
+    /** @name COM and internal init/term/mapping cruft.
+     * @{ */
+    DECLARE_EMPTY_CTOR_DTOR(GuestDnDSource)
+
+    int     init(const ComObjPtr<Guest>& pGuest);
+    void    uninit(void);
+
+    HRESULT FinalConstruct(void);
+    void    FinalRelease(void);
+    /** @}  */
+
+private:
+
+    /** Wrapped @name IDnDSource methods.
+     * @{ */
+    HRESULT dragIsPending(ULONG uScreenId, std::vector<com::Utf8Str> &aFormats, std::vector<DnDAction_T> &aAllowedActions, DnDAction_T *aDefaultAction);
+    HRESULT drop(const com::Utf8Str &aFormat, DnDAction_T aAction, ComPtr<IProgress> &aProgress);
+    HRESULT receiveData(std::vector<BYTE> &aData);
+    /** @}  */
+
+protected:
+
+    /** @name Attributes.
+     * @{ */
+    /** Pointer to guest implementation. */
+    const ComObjPtr<Guest>     m_pGuest;
+    /** @}  */
+};
+
+#endif /* !____H_GUESTDNDSOURCEIMPL */
+
Index: trunk/src/VBox/Main/include/GuestDnDTargetImpl.h
===================================================================
--- trunk/src/VBox/Main/include/GuestDnDTargetImpl.h	(revision 51476)
+++ trunk/src/VBox/Main/include/GuestDnDTargetImpl.h	(revision 51476)
@@ -0,0 +1,60 @@
+/* $Id$ */
+/** @file
+ * VBox Console COM Class implementation - Guest drag'n drop target.
+ */
+
+/*
+ * Copyright (C) 2014 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+#ifndef ____H_GUESTDNDTARGETIMPL
+#define ____H_GUESTDNDTARGETIMPL
+
+#include "GuestDnDTargetWrap.h"
+#include "GuestDnDPrivate.h"
+
+class ATL_NO_VTABLE GuestDnDTarget :
+    public GuestDnDTargetWrap
+{
+public:
+    /** @name COM and internal init/term/mapping cruft.
+     * @{ */
+    DECLARE_EMPTY_CTOR_DTOR(GuestDnDTarget)
+
+    int     init(const ComObjPtr<Guest>& pGuest);
+    void    uninit(void);
+
+    HRESULT FinalConstruct(void);
+    void    FinalRelease(void);
+    /** @}  */
+
+private:
+
+    /** Wrapped @name IDnDTarget methods.
+     * @{ */
+    HRESULT enter(ULONG aScreenId, ULONG ax, ULONG aY, DnDAction_T aDefaultAction, const std::vector<DnDAction_T> &aAllowedActions, const std::vector<com::Utf8Str> &aFormats, DnDAction_T *aResultAction);
+    HRESULT move(ULONG aScreenId, ULONG aX, ULONG aY, DnDAction_T aDefaultAction, const std::vector<DnDAction_T> &aAllowedActions, const std::vector<com::Utf8Str> &aFormats, DnDAction_T *aResultAction);
+    HRESULT leave(ULONG aScreenId);
+    HRESULT drop(ULONG aScreenId, ULONG aX, ULONG aY, DnDAction_T aDefaultAction, const std::vector<DnDAction_T> &aAllowedActions, const std::vector<com::Utf8Str> &aFormats, com::Utf8Str &aFormat, DnDAction_T *aResultAction);
+    HRESULT sendData(ULONG aScreenId, const com::Utf8Str &aFormat, const std::vector<BYTE> &aData, ComPtr<IProgress> &aProgress);
+    /** @}  */
+
+protected:
+
+    /** @name Attributes.
+     * @{ */
+    /** Pointer to guest implementation. */
+    const ComObjPtr<Guest>     m_pGuest;
+    /** @}  */
+};
+
+#endif /* !____H_GUESTDNDTARGETIMPL */
+
Index: trunk/src/VBox/Main/include/GuestImpl.h
===================================================================
--- trunk/src/VBox/Main/include/GuestImpl.h	(revision 51474)
+++ trunk/src/VBox/Main/include/GuestImpl.h	(revision 51476)
@@ -4,5 +4,5 @@
 
 /*
- * Copyright (C) 2006-2013 Oracle Corporation
+ * Copyright (C) 2006-2014 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
@@ -26,10 +26,10 @@
 #include "AdditionsFacilityImpl.h"
 #include "GuestCtrlImplPrivate.h"
+#ifdef VBOX_WITH_DRAG_AND_DROP
+# include "GuestDnDSourceImpl.h"
+# include "GuestDnDTargetImpl.h"
+#endif
 #include "GuestSessionImpl.h"
 #include "HGCM.h"
-
-#ifdef VBOX_WITH_DRAG_AND_DROP
-class GuestDnD;
-#endif
 
 typedef enum
@@ -48,7 +48,4 @@
 
 class Console;
-#ifdef VBOX_WITH_GUEST_CONTROL
-class Progress;
-#endif
 
 class ATL_NO_VTABLE Guest :
@@ -77,11 +74,13 @@
 
     // IGuest properties.
-    STDMETHOD(COMGETTER(OSTypeId)) (BSTR *aOSTypeId);
-    STDMETHOD(COMGETTER(AdditionsRunLevel)) (AdditionsRunLevelType_T *aRunLevel);
+    STDMETHOD(COMGETTER(OSTypeId))(BSTR *aOSTypeId);
+    STDMETHOD(COMGETTER(AdditionsRunLevel))(AdditionsRunLevelType_T *aRunLevel);
     STDMETHOD(COMGETTER(AdditionsVersion))(BSTR *a_pbstrAdditionsVersion);
     STDMETHOD(COMGETTER(AdditionsRevision))(ULONG *a_puAdditionsRevision);
+    STDMETHOD(COMGETTER(DnDSource))(IGuestDnDSource ** aSource);
+    STDMETHOD(COMGETTER(DnDTarget))(IGuestDnDTarget ** aTarget);
     STDMETHOD(COMGETTER(EventSource))(IEventSource ** aEventSource);
-    STDMETHOD(COMGETTER(Facilities)) (ComSafeArrayOut(IAdditionsFacility *, aFacilities));
-    STDMETHOD(COMGETTER(Sessions)) (ComSafeArrayOut(IGuestSession *, aSessions));
+    STDMETHOD(COMGETTER(Facilities))(ComSafeArrayOut(IAdditionsFacility *, aFacilities));
+    STDMETHOD(COMGETTER(Sessions))(ComSafeArrayOut(IGuestSession *, aSessions));
     STDMETHOD(COMGETTER(MemoryBalloonSize)) (ULONG *aMemoryBalloonSize);
     STDMETHOD(COMSETTER(MemoryBalloonSize)) (ULONG aMemoryBalloonSize);
@@ -93,13 +92,4 @@
     STDMETHOD(SetCredentials)(IN_BSTR aUsername, IN_BSTR aPassword,
                               IN_BSTR aDomain, BOOL aAllowInteractiveLogon);
-    // Drag'n drop support.
-    STDMETHOD(DragHGEnter)(ULONG uScreenId, ULONG uX, ULONG uY, DragAndDropAction_T defaultAction, ComSafeArrayIn(DragAndDropAction_T, allowedActions), ComSafeArrayIn(IN_BSTR, formats), DragAndDropAction_T *pResultAction);
-    STDMETHOD(DragHGMove)(ULONG uScreenId, ULONG uX, ULONG uY, DragAndDropAction_T defaultAction, ComSafeArrayIn(DragAndDropAction_T, allowedActions), ComSafeArrayIn(IN_BSTR, formats), DragAndDropAction_T *pResultAction);
-    STDMETHOD(DragHGLeave)(ULONG uScreenId);
-    STDMETHOD(DragHGDrop)(ULONG uScreenId, ULONG uX, ULONG uY, DragAndDropAction_T defaultAction, ComSafeArrayIn(DragAndDropAction_T, allowedActions), ComSafeArrayIn(IN_BSTR, formats), BSTR *pstrFormat, DragAndDropAction_T *pResultAction);
-    STDMETHOD(DragHGPutData)(ULONG uScreenId, IN_BSTR strFormat, ComSafeArrayIn(BYTE, data), IProgress **ppProgress);
-    STDMETHOD(DragGHPending)(ULONG uScreenId, ComSafeArrayOut(BSTR, formats), ComSafeArrayOut(DragAndDropAction_T, allowedActions), DragAndDropAction_T *pDefaultAction);
-    STDMETHOD(DragGHDropped)(IN_BSTR strFormat, DragAndDropAction_T action, IProgress **ppProgress);
-    STDMETHOD(DragGHGetData)(ComSafeArrayOut(BYTE, data));
     // Guest control.
     STDMETHOD(CreateSession)(IN_BSTR aUser, IN_BSTR aPassword, IN_BSTR aDomain, IN_BSTR aSessionName, IGuestSession **aGuestSession);
@@ -129,4 +119,5 @@
     bool facilityIsActive(VBoxGuestFacilityType enmFacility);
     void facilityUpdate(VBoxGuestFacilityType a_enmFacility, VBoxGuestFacilityStatus a_enmStatus, uint32_t a_fFlags, PCRTTIMESPEC a_pTimeSpecTS);
+    ComObjPtr<Console> getConsole(void) { return mParent; }
     void setAdditionsStatus(VBoxGuestFacilityType a_enmFacility, VBoxGuestFacilityStatus a_enmStatus, uint32_t a_fFlags, PCRTTIMESPEC a_pTimeSpecTS);
     void onUserStateChange(Bstr aUser, Bstr aDomain, VBoxGuestUserState enmState, const uint8_t *puDetails, uint32_t cbDetails);
@@ -142,5 +133,4 @@
     int         dispatchToSession(PVBOXGUESTCTRLHOSTCBCTX pCtxCb, PVBOXGUESTCTRLHOSTCALLBACK pSvcCb);
     uint32_t    getAdditionsVersion(void) { return mData.mAdditionsVersionFull; }
-    Console    *getConsole(void) { return mParent; }
     int         sessionRemove(GuestSession *pSession);
     int         sessionCreate(const GuestSessionStartupInfo &ssInfo, const GuestCredentials &guestCreds, ComObjPtr<GuestSession> &pGuestSession);
@@ -170,14 +160,14 @@
         { }
 
-        Bstr                    mOSTypeId;
-        FacilityMap             mFacilityMap;
-        AdditionsRunLevelType_T mAdditionsRunLevel;
-        uint32_t                mAdditionsVersionFull;
-        Bstr                    mAdditionsVersionNew;
-        uint32_t                mAdditionsRevision;
-        uint32_t                mAdditionsFeatures;
-        Bstr                    mInterfaceVersion;
-        GuestSessions           mGuestSessions;
-        uint32_t                mNextSessionID;
+        Bstr                        mOSTypeId;
+        FacilityMap                 mFacilityMap;
+        AdditionsRunLevelType_T     mAdditionsRunLevel;
+        uint32_t                    mAdditionsVersionFull;
+        Bstr                        mAdditionsVersionNew;
+        uint32_t                    mAdditionsRevision;
+        uint32_t                    mAdditionsFeatures;
+        Bstr                        mInterfaceVersion;
+        GuestSessions               mGuestSessions;
+        uint32_t                    mNextSessionID;
     } mData;
 
@@ -192,5 +182,5 @@
     BOOL                            mfPageFusionEnabled;
 
-    Console                        *mParent;
+    const ComObjPtr<Console>        mParent;
 
 #ifdef VBOX_WITH_GUEST_CONTROL
@@ -206,13 +196,14 @@
 
 #ifdef VBOX_WITH_DRAG_AND_DROP
-    GuestDnD         *m_pGuestDnD;
-    friend class GuestDnD;
-    friend class GuestDnDPrivate;
-#endif
-
-    RTTIMERLR         mStatTimer;
-    uint32_t          mMagic;
+    /** The guest's DnD source. */
+    const ComObjPtr<GuestDnDSource> mDnDSource;
+    /** The guest's DnD target. */
+    const ComObjPtr<GuestDnDTarget> mDnDTarget;
+#endif
+
+    RTTIMERLR                       mStatTimer;
+    uint32_t                        mMagic; /** @todo r=andy Rename this to something more meaningful. */
 };
-#define GUEST_MAGIC 0xCEED2006u
+#define GUEST_MAGIC 0xCEED2006u /** @todo r=andy Not very well defined!? */
 
 #endif // ____H_GUESTIMPL
Index: trunk/src/VBox/Main/include/MachineImpl.h
===================================================================
--- trunk/src/VBox/Main/include/MachineImpl.h	(revision 51474)
+++ trunk/src/VBox/Main/include/MachineImpl.h	(revision 51476)
@@ -297,5 +297,5 @@
 
         ClipboardMode_T     mClipboardMode;
-        DragAndDropMode_T   mDragAndDropMode;
+        DnDMode_T           mDnDMode;
 
         typedef std::map<Utf8Str, GuestProperty> GuestPropertyMap;
@@ -473,6 +473,6 @@
     STDMETHOD(COMGETTER(ClipboardMode))(ClipboardMode_T *aClipboardMode);
     STDMETHOD(COMSETTER(ClipboardMode))(ClipboardMode_T aClipboardMode);
-    STDMETHOD(COMGETTER(DragAndDropMode))(DragAndDropMode_T *aDragAndDropMode);
-    STDMETHOD(COMSETTER(DragAndDropMode))(DragAndDropMode_T aDragAndDropMode);
+    STDMETHOD(COMGETTER(DnDMode))(DnDMode_T *aDnDMode);
+    STDMETHOD(COMSETTER(DnDMode))(DnDMode_T aDnDMode);
     STDMETHOD(COMGETTER(GuestPropertyNotificationPatterns))(BSTR *aPattern);
     STDMETHOD(COMSETTER(GuestPropertyNotificationPatterns))(IN_BSTR aPattern);
@@ -749,5 +749,5 @@
     virtual HRESULT onSharedFolderChange() { return S_OK; }
     virtual HRESULT onClipboardModeChange(ClipboardMode_T /* aClipboardMode */) { return S_OK; }
-    virtual HRESULT onDragAndDropModeChange(DragAndDropMode_T /* aDragAndDropMode */) { return S_OK; }
+    virtual HRESULT onDnDModeChange(DnDMode_T /* aDnDMode */) { return S_OK; }
     virtual HRESULT onBandwidthGroupChange(IBandwidthGroup * /* aBandwidthGroup */) { return S_OK; }
     virtual HRESULT onStorageDeviceChange(IMediumAttachment * /* mediumAttachment */, BOOL /* remove */, BOOL /* silent */) { return S_OK; }
@@ -1139,5 +1139,5 @@
     HRESULT onSharedFolderChange();
     HRESULT onClipboardModeChange(ClipboardMode_T aClipboardMode);
-    HRESULT onDragAndDropModeChange(DragAndDropMode_T aDragAndDropMode);
+    HRESULT onDnDModeChange(DnDMode_T aDnDMode);
     HRESULT onBandwidthGroupChange(IBandwidthGroup *aBandwidthGroup);
     HRESULT onStorageDeviceChange(IMediumAttachment *aMediumAttachment, BOOL aRemove, BOOL aSilent);
Index: trunk/src/VBox/Main/include/SessionImpl.h
===================================================================
--- trunk/src/VBox/Main/include/SessionImpl.h	(revision 51474)
+++ trunk/src/VBox/Main/include/SessionImpl.h	(revision 51476)
@@ -4,5 +4,5 @@
 
 /*
- * Copyright (C) 2006-2013 Oracle Corporation
+ * Copyright (C) 2006-2014 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
@@ -92,5 +92,5 @@
     STDMETHOD(OnSharedFolderChange)(BOOL aGlobal);
     STDMETHOD(OnClipboardModeChange)(ClipboardMode_T aClipboardMode);
-    STDMETHOD(OnDragAndDropModeChange)(DragAndDropMode_T aDragAndDropMode);
+    STDMETHOD(OnDnDModeChange)(DnDMode_T aDnDMode);
     STDMETHOD(OnUSBDeviceAttach)(IUSBDevice *aDevice, IVirtualBoxErrorInfo *aError, ULONG aMaskedIfs);
     STDMETHOD(OnUSBDeviceDetach)(IN_BSTR aId, IVirtualBoxErrorInfo *aError);
Index: trunk/src/VBox/Main/src-client/ConsoleImpl.cpp
===================================================================
--- trunk/src/VBox/Main/src-client/ConsoleImpl.cpp	(revision 51474)
+++ trunk/src/VBox/Main/src-client/ConsoleImpl.cpp	(revision 51476)
@@ -5076,9 +5076,9 @@
 
 /**
- * Called by IInternalSessionControl::OnDragAndDropModeChange().
+ * Called by IInternalSessionControl::OnDnDModeChange().
  *
  * @note Locks this object for writing.
  */
-HRESULT Console::onDragAndDropModeChange(DragAndDropMode_T aDragAndDropMode)
+HRESULT Console::onDnDModeChange(DnDMode_T aDnDMode)
 {
     LogFlowThisFunc(("\n"));
@@ -5098,5 +5098,5 @@
             || mMachineState == MachineState_Teleporting
             || mMachineState == MachineState_LiveSnapshotting)
-            changeDragAndDropMode(aDragAndDropMode);
+            changeDnDMode(aDnDMode);
         else
             rc = setInvalidMachineStateError();
@@ -5108,5 +5108,5 @@
     {
         alock.release();
-        fireDragAndDropModeChangedEvent(mEventSource, aDragAndDropMode);
+        fireDnDModeChangedEvent(mEventSource, aDnDMode);
     }
 
@@ -8348,36 +8348,40 @@
  * Changes the drag'n_drop mode.
  *
- * @param aDragAndDropMode  new drag'n'drop mode.
+ * @param aDnDMode  new drag'n'drop mode.
  */
-void Console::changeDragAndDropMode(DragAndDropMode_T aDragAndDropMode)
+int Console::changeDnDMode(DnDMode_T aDnDMode)
 {
     VMMDev *pVMMDev = m_pVMMDev;
-    Assert(pVMMDev);
+    AssertPtrReturn(pVMMDev, VERR_INVALID_POINTER);
 
     VBOXHGCMSVCPARM parm;
+    RT_ZERO(parm);
     parm.type = VBOX_HGCM_SVC_PARM_32BIT;
 
-    switch (aDragAndDropMode)
+    switch (aDnDMode)
     {
         default:
-        case DragAndDropMode_Disabled:
-            LogRel(("Drag'n'drop mode: Off\n"));
+        case DnDMode_Disabled:
+            LogRel(("Changed drag'n drop mode to: Off\n"));
             parm.u.uint32 = VBOX_DRAG_AND_DROP_MODE_OFF;
             break;
-        case DragAndDropMode_GuestToHost:
-            LogRel(("Drag'n'drop mode: Guest to Host\n"));
+        case DnDMode_GuestToHost:
+            LogRel(("Changed drag'n drop mode to: Guest to Host\n"));
             parm.u.uint32 = VBOX_DRAG_AND_DROP_MODE_GUEST_TO_HOST;
             break;
-        case DragAndDropMode_HostToGuest:
-            LogRel(("Drag'n'drop mode: Host to Guest\n"));
+        case DnDMode_HostToGuest:
+            LogRel(("Changed drag'n drop mode to: Host to Guest\n"));
             parm.u.uint32 = VBOX_DRAG_AND_DROP_MODE_HOST_TO_GUEST;
             break;
-        case DragAndDropMode_Bidirectional:
-            LogRel(("Drag'n'drop mode: Bidirectional\n"));
+        case DnDMode_Bidirectional:
+            LogRel(("Changed drag'n drop mode to: Bidirectional\n"));
             parm.u.uint32 = VBOX_DRAG_AND_DROP_MODE_BIDIRECTIONAL;
             break;
     }
 
-    pVMMDev->hgcmHostCall("VBoxDragAndDropSvc", DragAndDropSvc::HOST_DND_SET_MODE, 1, &parm);
+    int rc = pVMMDev->hgcmHostCall("VBoxDragAndDropSvc",
+                                   DragAndDropSvc::HOST_DND_SET_MODE, 1, &parm);
+    LogFlowFunc(("rc=%Rrc\n", rc));
+    return rc;
 }
 
Index: trunk/src/VBox/Main/src-client/ConsoleImpl2.cpp
===================================================================
--- trunk/src/VBox/Main/src-client/ConsoleImpl2.cpp	(revision 51474)
+++ trunk/src/VBox/Main/src-client/ConsoleImpl2.cpp	(revision 51476)
@@ -24,5 +24,5 @@
 *   Header Files                                                               *
 *******************************************************************************/
-// for some reason Windows burns in sdk\...\winsock.h if this isn't included first
+/* For some reason Windows burns in sdk\...\winsock.h if this isn't included first. */
 #include "VBox/com/ptr.h"
 
@@ -33,5 +33,5 @@
 #endif
 #ifdef VBOX_WITH_DRAG_AND_DROP
-# include "GuestDnDImpl.h"
+# include "GuestDnDPrivate.h"
 #endif
 #include "VMMDev.h"
@@ -65,6 +65,6 @@
 #include <VBox/err.h>
 #include <VBox/param.h>
-#include <VBox/vmm/pdmapi.h> /* For PDMR3DriverAttach/PDMR3DriverDetach */
-#include <VBox/vmm/pdmusb.h> /* For PDMR3UsbCreateEmulatedDevice */
+#include <VBox/vmm/pdmapi.h> /* For PDMR3DriverAttach/PDMR3DriverDetach. */
+#include <VBox/vmm/pdmusb.h> /* For PDMR3UsbCreateEmulatedDevice. */
 #include <VBox/version.h>
 #include <VBox/HostServices/VBoxClipboardSvc.h>
@@ -77,6 +77,6 @@
 # include <VBox/com/defs.h>
 # include <VBox/com/array.h>
-# include "HGCM.h" /** @todo it should be possible to register a service
-                          * extension using a VMMDev callback. */
+# include "HGCM.h" /** @todo It should be possible to register a service
+                    *        extension using a VMMDev callback. */
 # include <vector>
 #endif /* VBOX_WITH_GUEST_PROPS */
@@ -2780,5 +2780,5 @@
 
         /*
-         * Clipboard
+         * Shared Clipboard.
          */
         {
@@ -2790,8 +2790,7 @@
                 /* Load the service */
                 rc = pVMMDev->hgcmLoadService("VBoxSharedClipboard", "VBoxSharedClipboard");
-
                 if (RT_FAILURE(rc))
                 {
-                    LogRel(("VBoxSharedClipboard is not available. rc = %Rrc\n", rc));
+                    LogRel(("Shared clipboard is not available, rc=%Rrc\n", rc));
                     /* That is not a fatal failure. */
                     rc = VINF_SUCCESS;
@@ -2799,4 +2798,6 @@
                 else
                 {
+                    LogRel(("Shared clipboard service loaded.\n"));
+
                     changeClipboardMode(mode);
 
@@ -2805,7 +2806,6 @@
                     parm.type = VBOX_HGCM_SVC_PARM_32BIT;
                     parm.setUInt32(!useHostClipboard());
-                    pVMMDev->hgcmHostCall("VBoxSharedClipboard", VBOX_SHARED_CLIPBOARD_HOST_FN_SET_HEADLESS, 1, &parm);
-
-                    Log(("Set VBoxSharedClipboard mode\n"));
+                    pVMMDev->hgcmHostCall("VBoxSharedClipboard",
+                                          VBOX_SHARED_CLIPBOARD_HOST_FN_SET_HEADLESS, 1, &parm);
                 }
             }
@@ -2813,5 +2813,5 @@
 
         /*
-         * HGCM HostChannel
+         * HGCM HostChannel.
          */
         {
@@ -2824,8 +2824,7 @@
             {
                 rc = pVMMDev->hgcmLoadService("VBoxHostChannel", "VBoxHostChannel");
-
                 if (RT_FAILURE(rc))
                 {
-                    LogRel(("VBoxHostChannel is not available. rc = %Rrc\n", rc));
+                    LogRel(("VBoxHostChannel is not available, rc=%Rrc\n", rc));
                     /* That is not a fatal failure. */
                     rc = VINF_SUCCESS;
@@ -2836,16 +2835,15 @@
 #ifdef VBOX_WITH_DRAG_AND_DROP
         /*
-         * Drag & Drop
+         * Drag'n Drop.
          */
         {
-            DragAndDropMode_T mode = DragAndDropMode_Disabled;
-            hrc = pMachine->COMGETTER(DragAndDropMode)(&mode);                              H();
+            DnDMode_T enmMode = DnDMode_Disabled;
+            hrc = pMachine->COMGETTER(DnDMode)(&enmMode);                                   H();
 
             /* Load the service */
             rc = pVMMDev->hgcmLoadService("VBoxDragAndDropSvc", "VBoxDragAndDropSvc");
-
             if (RT_FAILURE(rc))
             {
-                LogRel(("VBoxDragAndDropService is not available. rc = %Rrc\n", rc));
+                LogRel(("Drag'n drop service is not available, rc=%Rrc\n", rc));
                 /* That is not a fatal failure. */
                 rc = VINF_SUCCESS;
@@ -2855,12 +2853,12 @@
                 HGCMSVCEXTHANDLE hDummy;
                 rc = HGCMHostRegisterServiceExtension(&hDummy, "VBoxDragAndDropSvc",
-                                                      &GuestDnD::notifyGuestDragAndDropEvent,
-                                                      getGuest());
+                                                      &GuestDnD::notifyDnDDispatcher,
+                                                      GuestDnDInst());
                 if (RT_FAILURE(rc))
-                    Log(("Cannot register VBoxDragAndDropSvc extension!\n"));
+                    Log(("Cannot register VBoxDragAndDropSvc extension, rc=%Rrc\n", rc));
                 else
                 {
-                    changeDragAndDropMode(mode);
-                    Log(("VBoxDragAndDropSvc loaded\n"));
+                    LogRel(("Drag'n drop service loaded.\n"));
+                    rc = changeDnDMode(enmMode);
                 }
             }
@@ -2870,9 +2868,9 @@
 #ifdef VBOX_WITH_CROGL
         /*
-         * crOpenGL
+         * crOpenGL.
          */
         {
             BOOL fEnabled3D = false;
-            hrc = pMachine->COMGETTER(Accelerate3DEnabled)(&fEnabled3D); H();
+            hrc = pMachine->COMGETTER(Accelerate3DEnabled)(&fEnabled3D);                    H();
 
             if (fEnabled3D)
@@ -2887,9 +2885,9 @@
                                "or disable 3D acceleration in the VM settings"));
 
-                /* Load the service */
+                /* Load the service. */
                 rc = pVMMDev->hgcmLoadService("VBoxSharedCrOpenGL", "VBoxSharedCrOpenGL");
                 if (RT_FAILURE(rc))
                 {
-                    LogRel(("Failed to load Shared OpenGL service %Rrc\n", rc));
+                    LogRel(("Failed to load Shared OpenGL service, rc=%Rrc\n", rc));
                     /* That is not a fatal failure. */
                     rc = VINF_SUCCESS;
@@ -2913,9 +2911,9 @@
                     parm.u.pointer.addr = pVM;
                     parm.u.pointer.size = sizeof(pVM);
-                    rc = pVMMDev->hgcmHostCall("VBoxSharedCrOpenGL", SHCRGL_HOST_FN_SET_VM, SHCRGL_CPARMS_SET_VM, &parm);
+                    rc = pVMMDev->hgcmHostCall("VBoxSharedCrOpenGL",
+                                               SHCRGL_HOST_FN_SET_VM, SHCRGL_CPARMS_SET_VM, &parm);
                     if (!RT_SUCCESS(rc))
                         AssertMsgFailed(("SHCRGL_HOST_FN_SET_VM failed with %Rrc\n", rc));
                 }
-
             }
         }
@@ -2924,7 +2922,6 @@
 #ifdef VBOX_WITH_GUEST_PROPS
         /*
-         * Guest property service
+         * Guest property service.
          */
-
         rc = configGuestProperties(this, pUVM);
 #endif /* VBOX_WITH_GUEST_PROPS defined */
@@ -2932,7 +2929,6 @@
 #ifdef VBOX_WITH_GUEST_CONTROL
         /*
-         * Guest control service
+         * Guest control service.
          */
-
         rc = configGuestControl(this);
 #endif /* VBOX_WITH_GUEST_CONTROL defined */
@@ -5620,5 +5616,5 @@
             Log(("Cannot register VBoxGuestControlSvc extension!\n"));
         else
-            Log(("VBoxGuestControlSvc loaded\n"));
+            LogRel(("Guest Control service loaded.\n"));
     }
 
Index: trunk/src/VBox/Main/src-client/DisplayImpl.cpp
===================================================================
--- trunk/src/VBox/Main/src-client/DisplayImpl.cpp	(revision 51474)
+++ trunk/src/VBox/Main/src-client/DisplayImpl.cpp	(revision 51476)
@@ -2364,12 +2364,11 @@
 }
 
-
 // IDisplay methods
 /////////////////////////////////////////////////////////////////////////////
-STDMETHODIMP Display::GetScreenResolution (ULONG aScreenId,
-    ULONG *aWidth, ULONG *aHeight, ULONG *aBitsPerPixel,
-    LONG *aXOrigin, LONG *aYOrigin)
-{
-    LogRelFlowFunc(("aScreenId = %d\n", aScreenId));
+STDMETHODIMP Display::GetScreenResolution(ULONG aScreenId,
+                                          ULONG *aWidth, ULONG *aHeight, ULONG *aBitsPerPixel,
+                                          LONG *aXOrigin, LONG *aYOrigin)
+{
+    LogRelFlowFunc(("aScreenId=%RU32\n", aScreenId));
 
     AutoCaller autoCaller(this);
@@ -2446,28 +2445,27 @@
                                    (PFNRT)changeFramebuffer, 3, this, aFramebuffer, aScreenId);
 
+        ComAssertRCRet(vrc, E_FAIL);
         alock.acquire();
 
-        ComAssertRCRet (vrc, E_FAIL);
-
 #if defined(VBOX_WITH_HGCM) && defined(VBOX_WITH_CROGL)
-        {
-            BOOL is3denabled;
-            mParent->machine()->COMGETTER(Accelerate3DEnabled)(&is3denabled);
-
-            if (is3denabled)
-            {
-                VBOXCRCMDCTL_HGCM data;
-                data.Hdr.enmType = VBOXCRCMDCTL_TYPE_HGCM;
-                data.Hdr.u32Function = SHCRGL_HOST_FN_SCREEN_CHANGED;
-
-                data.aParms[0].type = VBOX_HGCM_SVC_PARM_32BIT;
-                data.aParms[0].u.uint32 = aScreenId;
-
-                alock.release();
-
-                crCtlSubmitSync(&data.Hdr, sizeof (data));
-
-                alock.acquire();
-            }
+        BOOL fIs3DEnabled;
+        HRESULT hr = mParent->machine()->COMGETTER(Accelerate3DEnabled)(&fIs3DEnabled);
+        ComAssertComRC(hr);
+        if (fIs3DEnabled)
+        {
+            VBOXCRCMDCTL_HGCM data;
+            RT_ZERO(data);
+            data.Hdr.enmType = VBOXCRCMDCTL_TYPE_HGCM;
+            data.Hdr.u32Function = SHCRGL_HOST_FN_SCREEN_CHANGED;
+
+            data.aParms[0].type = VBOX_HGCM_SVC_PARM_32BIT;
+            data.aParms[0].u.uint32 = aScreenId;
+
+            alock.release();
+
+            vrc = crCtlSubmitSync(&data.Hdr, sizeof(data));
+            AssertRC(vrc);
+
+            alock.acquire();
         }
 #endif /* #if defined(VBOX_WITH_HGCM) && defined(VBOX_WITH_CROGL) */
@@ -2476,6 +2474,6 @@
     {
         /* No VM is created (VM is powered off), do a direct call */
-        int vrc = changeFramebuffer (this, aFramebuffer, aScreenId);
-        ComAssertRCRet (vrc, E_FAIL);
+        int vrc = changeFramebuffer(this, aFramebuffer, aScreenId);
+        ComAssertRCRet(vrc, E_FAIL);
     }
 
@@ -2605,5 +2603,5 @@
                                      IFramebuffer **aFramebuffer, LONG *aXOrigin, LONG *aYOrigin)
 {
-    LogRelFlowFunc(("aScreenId = %d\n", aScreenId));
+    LogRelFlowFunc(("aScreenId=%ld\n", aScreenId));
 
     CheckComArgOutPointerValid(aFramebuffer);
@@ -2617,10 +2615,11 @@
         return E_INVALIDARG;
 
-    /* @todo this should be actually done on EMT. */
+    /** @todo This should be actually done on EMT. */
     DISPLAYFBINFO *pFBInfo = &maFramebuffers[aScreenId];
-
-    *aFramebuffer = pFBInfo->pFramebuffer;
+    AssertPtr(pFBInfo);
+
+    *aFramebuffer = pFBInfo->pFramebuffer; /** @todo r=andy Race prone? Use a ComPtr instead? */
     if (*aFramebuffer)
-        (*aFramebuffer)->AddRef ();
+        (*aFramebuffer)->AddRef();
     if (aXOrigin)
         *aXOrigin = pFBInfo->xOrigin;
@@ -2643,5 +2642,5 @@
 
     /*
-     * Do some rough checks for valid input
+     * Do some rough checks for valid input.
      */
     ULONG width  = aWidth;
Index: trunk/src/VBox/Main/src-client/GuestDnDImpl.cpp
===================================================================
--- trunk/src/VBox/Main/src-client/GuestDnDImpl.cpp	(revision 51474)
+++ 	(revision )
@@ -1,1390 +1,0 @@
-/* $Id$ */
-/** @file
- * VirtualBox COM class implementation: Guest Drag and Drop parts
- */
-
-/*
- * Copyright (C) 2011-2014 Oracle Corporation
- *
- * This file is part of VirtualBox Open Source Edition (OSE), as
- * available from http://www.virtualbox.org. This file is free software;
- * you can redistribute it and/or modify it under the terms of the GNU
- * General Public License (GPL) as published by the Free Software
- * Foundation, in version 2 as it comes in the "COPYING" file of the
- * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
- * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
- */
-
-#include "GuestImpl.h"
-#include "AutoCaller.h"
-
-#ifdef VBOX_WITH_DRAG_AND_DROP
-# include "ConsoleImpl.h"
-# include "ProgressImpl.h"
-# include "GuestDnDImpl.h"
-
-# include <iprt/dir.h>
-# include <iprt/path.h>
-# include <iprt/stream.h>
-# include <iprt/semaphore.h>
-# include <iprt/cpp/utils.h>
-
-# include <VMMDev.h>
-
-# include <VBox/com/list.h>
-# include <VBox/GuestHost/DragAndDrop.h>
-# include <VBox/HostServices/DragAndDropSvc.h>
-
-# ifdef LOG_GROUP
- # undef LOG_GROUP
-# endif
-# define LOG_GROUP LOG_GROUP_GUEST_DND
-# include <VBox/log.h>
-
-/* How does this work:
- *
- * Drag and Drop is handled over the internal HGCM service for the host <->
- * guest communication. Beside that we need to map the Drag and Drop protocols
- * of the various OS's we support to our internal channels, this is also highly
- * communicative in both directions. Unfortunately HGCM isn't really designed
- * for that. Next we have to foul some of the components. This includes to
- * trick X11 on the guest side, but also Qt needs to be tricked on the host
- * side a little bit.
- *
- * The following components are involved:
- *
- * 1. GUI: Uses the Qt classes for Drag and Drop and mainly forward the content
- *    of it to the Main IGuest interface (see UIDnDHandler.cpp).
- * 2. Main: Public interface for doing Drag and Drop. Also manage the IProgress
- *    interfaces for blocking the caller by showing a progress dialog (see
- *    this file).
- * 3. HGCM service: Handle all messages from the host to the guest at once and
- *    encapsulate the internal communication details (see dndmanager.cpp and
- *    friends).
- * 4. Guest additions: Split into the platform neutral part (see
- *    VBoxGuestR3LibDragAndDrop.cpp) and the guest OS specific parts.
- *    Receive/send message from/to the HGCM service and does all guest specific
- *    operations. Currently only X11 is supported (see draganddrop.cpp within
- *    VBoxClient).
- *
- * Host -> Guest:
- * 1. There are DnD Enter, Move, Leave events which are send exactly like this
- *    to the guest. The info includes the pos, mimetypes and allowed actions.
- *    The guest has to respond with an action it would accept, so the GUI could
- *    change the cursor.
- * 2. On drop, first a drop event is send. If this is accepted a drop data
- *    event follows. This blocks the GUI and shows some progress indicator.
- *
- * Guest -> Host:
- * 1. The GUI is asking the guest if a DnD event is pending when the user moves
- *    the cursor out of the view window. If so, this returns the mimetypes and
- *    allowed actions.
- * (2. On every mouse move this is asked again, to make sure the DnD event is
- *     still valid.)
- * 3. On drop the host request the data from the guest. This blocks the GUI and
- *    shows some progress indicator.
- *
- * Some hints:
- * m_sstrAllowedMimeTypes here in this file defines the allowed mime-types.
- * This is necessary because we need special handling for some of the
- * mime-types. E.g. for URI lists we need to transfer the actual dirs and
- * files. Text EOL may to be changed. Also unknown mime-types may need special
- * handling as well, which may lead to undefined behavior in the host/guest, if
- * not done.
- *
- * Dropping of a directory, means recursively transferring _all_ the content.
- *
- * Directories and files are placed into the user's temporary directory on the
- * guest (e.g. /tmp/VirtualBox Dropped Files). We can't delete them after the
- * DnD operation, because we didn't know what the DnD target does with it. E.g.
- * it could just be opened in place. This could lead ofc to filling up the disk
- * within the guest. To inform the user about this, a small app could be
- * developed which scans this directory regularly and inform the user with a
- * tray icon hint (and maybe the possibility to clean this up instantly). The
- * same has to be done in the G->H direction when it is implemented.
- *
- * Of course only regularly files are supported. Symlinks are resolved and
- * transfered as regularly files. First we don't know if the other side support
- * symlinks at all and second they could point to somewhere in a directory tree
- * which not exists on the other side.
- *
- * The code tries to preserve the file modes of the transfered dirs/files. This
- * is useful (and maybe necessary) for two things:
- * 1. If a file is executable, it should be also after the transfer, so the
- *    user can just execute it, without manually tweaking the modes first.
- * 2. If a dir/file is not accessible by group/others in the host, it shouldn't
- *    be in the guest.
- * In any case, the user mode is always set to rwx (so that we can access it
- * ourself, in e.g. for a cleanup case after cancel).
- *
- * Cancel is supported in both directions and cleans up all previous steps
- * (thats is: deleting already transfered dirs/files).
- *
- * In general I propose the following changes in the VBox HGCM infrastructure
- * for the future:
- * - Currently it isn't really possible to send messages to the guest from the
- *   host. The host informs the guest just that there is something, the guest
- *   than has to ask which message and depending on that send the appropriate
- *   message to the host, which is filled with the right data.
- * - There is no generic interface for sending bigger memory blocks to/from the
- *   guest. This is now done here, but I guess was also necessary for e.g.
- *   guest execution. So something generic which brake this up into smaller
- *   blocks and send it would be nice (with all the error handling and such
- *   ofc).
- * - I developed a "protocol" for the DnD communication here. So the host and
- *   the guest have always to match in the revision. This is ofc bad, because
- *   the additions could be outdated easily. So some generic protocol number
- *   support in HGCM for asking the host and the guest of the support version,
- *   would be nice. Ofc at least the host should be able to talk to the guest,
- *   even when the version is below the host one.
- * All this stuff would be useful for the current services, but also for future
- * onces.
- *
- * Todo:
- * - Dragging out of the guest (partly done)
- *   - ESC doesn't really work (on Windows guests it's already implemented)
- *   - transfer of URIs (that is the files and patching of the data)
- *   - testing in a multi monitor setup
- *   ... in any case it seems a little bit difficult to handle from the Qt
- *   side. Maybe also a host specific implementation becomes necessary ...
- *   this would be really worst ofc.
- * - Win guest support (maybe there have to be done a mapping between the
- *   official mime-types and Win Clipboard formats (see QWindowsMime, for an
- *   idea), for VBox internally only mime-types should be used)
- * - EOL handling on text (should be shared with the clipboard code)
- * - add configuration (GH, HG, Bidirectional, None), like for the clipboard
- * - HG->GH and GH->HG-switch: Handle the case the user drags something out of
- *   the guest and than return to the source view (or another window in the
- *   multiple guest screen scenario).
- * - add support for more mime-types (especially images, csv)
- * - test unusual behavior:
- *   - DnD service crash in the guest during a DnD op (e.g. crash of VBoxClient or X11)
- *   - not expected order of the events between HGCM and the guest
- * - Security considerations: We transfer a lot of memory between the guest and
- *   the host and even allow the creation of dirs/files. Maybe there should be
- *   limits introduced to preventing DOS attacks or filling up all the memory
- *   (both in the host and the guest).
- * - test, test, test ...
- */
-
-class DnDGuestResponse
-{
-
-public:
-
-    DnDGuestResponse(const ComObjPtr<Guest>& pGuest);
-
-    virtual ~DnDGuestResponse(void);
-
-public:
-
-    int notifyAboutGuestResponse(void);
-    int waitForGuestResponse(RTMSINTERVAL msTimeout = 500);
-
-    void setDefAction(uint32_t a) { m_defAction = a; }
-    uint32_t defAction(void) const { return m_defAction; }
-
-    void setAllActions(uint32_t a) { m_allActions = a; }
-    uint32_t allActions() const { return m_allActions; }
-
-    void setFormat(const Utf8Str &strFormat) { m_strFormat = strFormat; }
-    Utf8Str format(void) const { return m_strFormat; }
-
-    void setDropDir(const Utf8Str &strDropDir) { m_strDropDir = strDropDir; }
-    Utf8Str dropDir(void) const { return m_strDropDir; }
-
-    int dataAdd(const void *pvData, uint32_t cbData, uint32_t *pcbCurSize);
-    int dataSetStatus(size_t cbDataAdd, size_t cbDataTotal = 0);
-    void reset(void);
-    const void *data(void) { return m_pvData; }
-    size_t size(void) const { return m_cbData; }
-
-    int setProgress(unsigned uPercentage, uint32_t uState, int rcOp = VINF_SUCCESS);
-    HRESULT resetProgress(const ComObjPtr<Guest>& pParent);
-    HRESULT queryProgressTo(IProgress **ppProgress);
-
-    int writeToFile(const char *pszPath, size_t cbPath, void *pvData, size_t cbData, uint32_t fMode);
-
-public:
-
-    Utf8Str errorToString(const ComObjPtr<Guest>& pGuest, int guestRc);
-
-private:
-    RTSEMEVENT           m_EventSem;
-    uint32_t             m_defAction;
-    uint32_t             m_allActions;
-    Utf8Str              m_strFormat;
-
-    /** The actual MIME data.*/
-    void                *m_pvData;
-    /** Size (in bytes) of MIME data. */
-    uint32_t             m_cbData;
-
-    size_t               m_cbDataCurrent;
-    size_t               m_cbDataTotal;
-    /** Dropped files directory on the host. */
-    Utf8Str              m_strDropDir;
-    /** The handle of the currently opened file being written to
-     *  or read from. */
-    RTFILE               m_hFile;
-    Utf8Str              m_strFile;
-
-    ComObjPtr<Guest>     m_parent;
-    ComObjPtr<Progress>  m_progress;
-};
-
-/** @todo This class needs a major cleanup. Later. */
-class GuestDnDPrivate
-{
-private:
-
-    /** @todo Currently we only support one response. Maybe this needs to be extended at some time. */
-    GuestDnDPrivate(GuestDnD *q, const ComObjPtr<Guest>& pGuest)
-        : q_ptr(q)
-        , p(pGuest)
-        , m_pDnDResponse(new DnDGuestResponse(pGuest))
-    {}
-    virtual ~GuestDnDPrivate(void) { delete m_pDnDResponse; }
-
-    DnDGuestResponse *response(void) const { return m_pDnDResponse; }
-
-    HRESULT adjustCoords(ULONG uScreenId, ULONG *puX, ULONG *puY) const;
-    int hostCall(uint32_t u32Function, uint32_t cParms, PVBOXHGCMSVCPARM paParms) const;
-
-    /* Static helpers. */
-    static RTCString           toFormatString(ComSafeArrayIn(IN_BSTR, formats));
-    static void                toFormatSafeArray(const RTCString &strFormats, ComSafeArrayOut(BSTR, formats));
-
-    static DragAndDropAction_T toMainAction(uint32_t uAction);
-    static void                toMainActions(uint32_t uActions, ComSafeArrayOut(DragAndDropAction_T, actions));
-    static uint32_t            toHGCMAction(DragAndDropAction_T action);
-    static void                toHGCMActions(DragAndDropAction_T inDefAction, uint32_t *pOutDefAction,
-                                             ComSafeArrayIn(DragAndDropAction_T, inAllowedActions),
-                                             uint32_t *pOutAllowedActions);
-
-    /* Private q and parent pointer */
-    GuestDnD                        *q_ptr;
-    ComObjPtr<Guest>                 p;
-
-    /* Private helper members. */
-    static const RTCList<RTCString>  m_sstrAllowedMimeTypes;
-    DnDGuestResponse                *m_pDnDResponse;
-
-    friend class GuestDnD;
-};
-
-/* What mime-types are supported by VirtualBox.
- * Note: If you add something here, make sure you test it with all guest OS's!
- ** @todo Make this MIME list configurable / extendable (by extra data?). Currently
- *        this is done hardcoded on every guest platform (POSIX/Windows).
- */
-/* static */
-const RTCList<RTCString> GuestDnDPrivate::m_sstrAllowedMimeTypes = RTCList<RTCString>()
-    /* Uri's */
-    << "text/uri-list"
-    /* Text */
-    << "text/plain;charset=utf-8"
-    << "UTF8_STRING"
-    << "text/plain"
-    << "COMPOUND_TEXT"
-    << "TEXT"
-    << "STRING"
-    /* OpenOffice formates */
-    << "application/x-openoffice-embed-source-xml;windows_formatname=\"Star Embed Source (XML)\""
-    << "application/x-openoffice-drawing;windows_formatname=\"Drawing Format\"";
-
-DnDGuestResponse::DnDGuestResponse(const ComObjPtr<Guest>& pGuest)
-  : m_EventSem(NIL_RTSEMEVENT)
-  , m_defAction(0)
-  , m_allActions(0)
-  , m_pvData(0)
-  , m_cbData(0)
-  , m_cbDataCurrent(0)
-  , m_cbDataTotal(0)
-  , m_hFile(NIL_RTFILE)
-  , m_parent(pGuest)
-{
-    int rc = RTSemEventCreate(&m_EventSem);
-    AssertRC(rc);
-}
-
-DnDGuestResponse::~DnDGuestResponse(void)
-{
-    reset();
-
-    int rc = RTSemEventDestroy(m_EventSem);
-    AssertRC(rc);
-}
-
-int DnDGuestResponse::dataAdd(const void *pvData, uint32_t cbData,
-                              uint32_t *pcbCurSize)
-{
-    AssertPtrReturn(pvData, VERR_INVALID_POINTER);
-    AssertReturn(cbData, VERR_INVALID_PARAMETER);
-    /* pcbCurSize is optional. */
-
-    int rc = VINF_SUCCESS;
-
-    /** @todo Make reallocation scheme a bit smarter here. */
-    m_pvData = RTMemRealloc(m_pvData, m_cbData + cbData);
-    if (m_pvData)
-    {
-        memcpy(&static_cast<uint8_t*>(m_pvData)[m_cbData],
-               pvData, cbData);
-        m_cbData += cbData;
-
-        if (pcbCurSize)
-            *pcbCurSize = m_cbData;
-    }
-    else
-        rc = VERR_NO_MEMORY;
-
-    return rc;
-}
-
-/* static */
-Utf8Str DnDGuestResponse::errorToString(const ComObjPtr<Guest>& pGuest, int guestRc)
-{
-    Utf8Str strError;
-
-    switch (guestRc)
-    {
-        case VERR_ACCESS_DENIED:
-            strError += Utf8StrFmt(pGuest->tr("For one or more guest files or directories selected for transferring to the host your guest "
-                                              "user does not have the appropriate access rights for. Please make sure that all selected "
-                                              "elements can be accessed and that your guest user has the appropriate rights."));
-            break;
-
-        case VERR_NOT_FOUND:
-            /* Should not happen due to file locking on the guest, but anyway ... */
-            strError += Utf8StrFmt(pGuest->tr("One or more guest files or directories selected for transferring to the host were not"
-                                              "found on the guest anymore. This can be the case if the guest files were moved and/or"
-                                              "altered while the drag'n drop operation was in progress."));
-            break;
-
-        case VERR_SHARING_VIOLATION:
-            strError += Utf8StrFmt(pGuest->tr("One or more guest files or directories selected for transferring to the host were locked. "
-                                              "Please make sure that all selected elements can be accessed and that your guest user has "
-                                              "the appropriate rights."));
-            break;
-
-        default:
-            strError += Utf8StrFmt("Drag'n drop guest error (%Rrc)", guestRc);
-            break;
-    }
-
-    return strError;
-}
-
-int DnDGuestResponse::notifyAboutGuestResponse(void)
-{
-    return RTSemEventSignal(m_EventSem);
-}
-
-void DnDGuestResponse::reset(void)
-{
-    LogFlowThisFuncEnter();
-
-    m_defAction = 0;
-    m_allActions = 0;
-
-    m_strDropDir = "";
-    m_strFormat = "";
-
-    if (m_pvData)
-    {
-        RTMemFree(m_pvData);
-        m_pvData = NULL;
-    }
-    m_cbData = 0;
-    m_cbDataCurrent = 0;
-    m_cbDataTotal = 0;
-
-    if (m_hFile != NIL_RTFILE)
-    {
-        RTFileClose(m_hFile);
-        m_hFile = NIL_RTFILE;
-    }
-    m_strFile = "";
-}
-
-HRESULT DnDGuestResponse::resetProgress(const ComObjPtr<Guest>& pParent)
-{
-    m_progress.setNull();
-    HRESULT rc = m_progress.createObject();
-    if (SUCCEEDED(rc))
-    {
-        rc = m_progress->init(static_cast<IGuest*>(pParent),
-                              Bstr(pParent->tr("Dropping data")).raw(),
-                              TRUE);
-    }
-    return rc;
-}
-
-int DnDGuestResponse::setProgress(unsigned uPercentage,
-                                  uint32_t uState, int rcOp /* = VINF_SUCCESS */)
-{
-    LogFlowFunc(("uPercentage=%RU32, uState=%RU32, rcOp=%Rrc\n",
-                 uPercentage, uState, rcOp));
-
-    int vrc = VINF_SUCCESS;
-    if (!m_progress.isNull())
-    {
-        BOOL fCompleted;
-        HRESULT hr = m_progress->COMGETTER(Completed)(&fCompleted);
-        if (!fCompleted)
-        {
-            if (uState == DragAndDropSvc::DND_PROGRESS_ERROR)
-            {
-                hr = m_progress->i_notifyComplete(VBOX_E_IPRT_ERROR,
-                                                  COM_IIDOF(IGuest),
-                                                  m_parent->getComponentName(),
-                                                  DnDGuestResponse::errorToString(m_parent, rcOp).c_str());
-                reset();
-            }
-            else if (uState == DragAndDropSvc::DND_PROGRESS_CANCELLED)
-            {
-                hr = m_progress->Cancel();
-                if (SUCCEEDED(hr))
-                    vrc = VERR_CANCELLED;
-
-                reset();
-            }
-            else /* uState == DragAndDropSvc::DND_PROGRESS_RUNNING */
-            {
-                hr = m_progress->SetCurrentOperationProgress(uPercentage);
-                AssertComRC(hr);
-                if (   uState      == DragAndDropSvc::DND_PROGRESS_COMPLETE
-                    || uPercentage >= 100)
-                    hr = m_progress->i_notifyComplete(S_OK);
-            }
-        }
-    }
-
-    return vrc;
-}
-
-int DnDGuestResponse::dataSetStatus(size_t cbDataAdd, size_t cbDataTotal /* = 0 */)
-{
-    if (cbDataTotal)
-    {
-#ifndef DEBUG_andy
-        AssertMsg(m_cbDataTotal <= cbDataTotal, ("New data size must not be smaller (%zu) than old value (%zu)\n",
-                                                 cbDataTotal, m_cbDataTotal));
-#endif
-        LogFlowFunc(("Updating total data size from %zu to %zu\n", m_cbDataTotal, cbDataTotal));
-        m_cbDataTotal = cbDataTotal;
-    }
-    AssertMsg(m_cbDataTotal, ("m_cbDataTotal must not be <= 0\n"));
-
-    m_cbDataCurrent += cbDataAdd;
-    unsigned int cPercentage = RT_MIN(m_cbDataCurrent * 100.0 / m_cbDataTotal, 100);
-
-    /** @todo Don't use anonymous enums (uint32_t). */
-    uint32_t uStatus = DragAndDropSvc::DND_PROGRESS_RUNNING;
-    if (m_cbDataCurrent >= m_cbDataTotal)
-        uStatus = DragAndDropSvc::DND_PROGRESS_COMPLETE;
-
-#ifdef DEBUG_andy
-    LogFlowFunc(("Updating transfer status (%zu/%zu), status=%ld\n",
-                 m_cbDataCurrent, m_cbDataTotal, uStatus));
-#else
-    AssertMsg(m_cbDataCurrent <= m_cbDataTotal,
-              ("More data transferred (%zu) than initially announced (%zu), cbDataAdd=%zu\n",
-              m_cbDataCurrent, m_cbDataTotal, cbDataAdd));
-#endif
-    int rc = setProgress(cPercentage, uStatus);
-
-    /** @todo For now we instantly confirm the cancel. Check if the
-     *        guest should first clean up stuff itself and than really confirm
-     *        the cancel request by an extra message. */
-    if (rc == VERR_CANCELLED)
-        rc = setProgress(100, DragAndDropSvc::DND_PROGRESS_CANCELLED);
-
-    LogFlowFuncLeaveRC(rc);
-    return rc;
-}
-
-HRESULT DnDGuestResponse::queryProgressTo(IProgress **ppProgress)
-{
-    return m_progress.queryInterfaceTo(ppProgress);
-}
-
-int DnDGuestResponse::waitForGuestResponse(RTMSINTERVAL msTimeout /*= 500 */)
-{
-    int rc = RTSemEventWait(m_EventSem, msTimeout);
-#ifdef DEBUG_andy
-    LogFlowFunc(("msTimeout=%RU32, rc=%Rrc\n", msTimeout, rc));
-#endif
-    return rc;
-}
-
-int DnDGuestResponse::writeToFile(const char *pszPath, size_t cbPath,
-                                  void *pvData, size_t cbData, uint32_t fMode)
-{
-    /** @todo Support locking more than one file at a time! We
-     *        might want to have a table in DnDGuestImpl which
-     *        keeps those file pointers around, or extend the
-     *        actual protocol for explicit open calls.
-     *
-     *        For now we only keep one file open at a time, so if
-     *        a client does alternating writes to different files
-     *        this function will close the old and re-open the new
-     *        file on every call. */
-    int rc;
-    if (   m_hFile == NIL_RTFILE
-        || m_strFile != pszPath)
-    {
-        char *pszFile = RTPathJoinA(m_strDropDir.c_str(), pszPath);
-        if (pszFile)
-        {
-            RTFILE hFile;
-            /** @todo Respect fMode!  */
-            rc = RTFileOpen(&hFile, pszFile,
-                              RTFILE_O_OPEN_CREATE | RTFILE_O_DENY_WRITE
-                            | RTFILE_O_WRITE | RTFILE_O_APPEND);
-            if (RT_SUCCESS(rc))
-            {
-                LogFlowFunc(("Opening \"%s\" (fMode=0x%x) for writing ...\n",
-                             pszFile, fMode));
-
-                m_hFile = hFile;
-                m_strFile = pszPath;
-            }
-
-            RTStrFree(pszFile);
-        }
-        else
-            rc = VERR_NO_MEMORY;
-    }
-    else
-        rc = VINF_SUCCESS;
-
-    if (RT_SUCCESS(rc))
-    {
-        rc = RTFileWrite(m_hFile, pvData, cbData,
-                         NULL /* No partial writes */);
-
-        if (RT_SUCCESS(rc))
-            rc = dataSetStatus(cbData);
-    }
-
-    return rc;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-HRESULT GuestDnDPrivate::adjustCoords(ULONG uScreenId, ULONG *puX, ULONG *puY) const
-{
-    /* For multi-monitor support we need to add shift values to the coordinates
-     * (depending on the screen number). */
-    ComPtr<IDisplay> pDisplay;
-    HRESULT hr = p->mParent->COMGETTER(Display)(pDisplay.asOutParam());
-    if (FAILED(hr))
-        return hr;
-
-    LONG xShift, yShift;
-    hr = pDisplay->GetScreenResolution(uScreenId, NULL, NULL, NULL,
-                                       &xShift, &yShift);
-    if (FAILED(hr))
-        return hr;
-
-    *puX += xShift;
-    *puY += yShift;
-
-    return hr;
-}
-
-int GuestDnDPrivate::hostCall(uint32_t u32Function, uint32_t cParms,
-                              PVBOXHGCMSVCPARM paParms) const
-{
-    VMMDev *pVMMDev = NULL;
-    {
-        /* Make sure mParent is valid, so set the read lock while using.
-         * Do not keep this lock while doing the actual call, because in the meanwhile
-         * another thread could request a write lock which would be a bad idea ... */
-        AutoReadLock alock(p COMMA_LOCKVAL_SRC_POS);
-
-        /* Forward the information to the VMM device. */
-        AssertPtr(p->mParent);
-        pVMMDev = p->mParent->getVMMDev();
-    }
-
-    if (!pVMMDev)
-        throw p->setError(VBOX_E_VM_ERROR,
-                          p->tr("VMM device is not available (is the VM running?)"));
-
-    LogFlowFunc(("hgcmHostCall uMsg=%RU32, cParms=%RU32\n", u32Function, cParms));
-    int rc = pVMMDev->hgcmHostCall("VBoxDragAndDropSvc",
-                                   u32Function,
-                                   cParms, paParms);
-    if (RT_FAILURE(rc))
-    {
-        LogFlowFunc(("hgcmHostCall failed with rc=%Rrc\n", rc));
-        throw p->setError(VBOX_E_IPRT_ERROR,
-                          p->tr("hgcmHostCall failed (%Rrc)"), rc);
-    }
-
-    return rc;
-}
-
-/* static */
-RTCString GuestDnDPrivate::toFormatString(ComSafeArrayIn(IN_BSTR, formats))
-{
-    const RTCList<Utf8Str> formatList(ComSafeArrayInArg(formats));
-    RTCString strFormat;
-    for (size_t i = 0; i < formatList.size(); ++i)
-    {
-        const RTCString &f = formatList.at(i);
-        /* Only keep allowed format types. */
-        if (m_sstrAllowedMimeTypes.contains(f))
-            strFormat += f + "\r\n";
-    }
-    return strFormat;
-}
-
-/* static */
-void GuestDnDPrivate::toFormatSafeArray(const RTCString &strFormats, ComSafeArrayOut(BSTR, formats))
-{
-    RTCList<RTCString> list = strFormats.split("\r\n");
-    size_t i = 0;
-    while (i < list.size())
-    {
-        /* Only keep allowed format types. */
-        if (!m_sstrAllowedMimeTypes.contains(list.at(i)))
-            list.removeAt(i);
-        else
-            ++i;
-    }
-    /* Create a safe array out of the cleaned list. */
-    com::SafeArray<BSTR> sfaFormats(list.size());
-    for (i = 0; i < list.size(); ++i)
-    {
-        const RTCString &f = list.at(i);
-        if (m_sstrAllowedMimeTypes.contains(f))
-        {
-            Bstr bstr(f);
-            bstr.detachTo(&sfaFormats[i]);
-        }
-    }
-    sfaFormats.detachTo(ComSafeArrayOutArg(formats));
-}
-
-/* static */
-uint32_t GuestDnDPrivate::toHGCMAction(DragAndDropAction_T action)
-{
-    uint32_t a = DND_IGNORE_ACTION;
-    switch (action)
-    {
-        case DragAndDropAction_Copy:   a = DND_COPY_ACTION; break;
-        case DragAndDropAction_Move:   a = DND_MOVE_ACTION; break;
-        case DragAndDropAction_Link:   /* For now it doesn't seems useful to allow a link
-                                          action between host & guest. Maybe later! */
-        case DragAndDropAction_Ignore: /* Ignored */ break;
-        default: AssertMsgFailed(("Action %u not recognized!\n", action)); break;
-    }
-    return a;
-}
-
-/* static */
-void GuestDnDPrivate::toHGCMActions(DragAndDropAction_T inDefAction,
-                                    uint32_t *pOutDefAction,
-                                    ComSafeArrayIn(DragAndDropAction_T, inAllowedActions),
-                                    uint32_t *pOutAllowedActions)
-{
-    const com::SafeArray<DragAndDropAction_T> sfaInActions(ComSafeArrayInArg(inAllowedActions));
-
-    /* Defaults */
-    *pOutDefAction = toHGCMAction(inDefAction);;
-    *pOutAllowedActions = DND_IGNORE_ACTION;
-
-    /* First convert the allowed actions to a bit array. */
-    for (size_t i = 0; i < sfaInActions.size(); ++i)
-        *pOutAllowedActions |= toHGCMAction(sfaInActions[i]);
-
-    /* Second check if the default action is a valid action and if not so try
-     * to find an allowed action. */
-    if (isDnDIgnoreAction(*pOutDefAction))
-    {
-        if (hasDnDCopyAction(*pOutAllowedActions))
-            *pOutDefAction = DND_COPY_ACTION;
-        else if (hasDnDMoveAction(*pOutAllowedActions))
-            *pOutDefAction = DND_MOVE_ACTION;
-    }
-}
-
-/* static */
-DragAndDropAction_T GuestDnDPrivate::toMainAction(uint32_t uAction)
-{
-    /* For now it doesn't seems useful to allow a
-     * link action between host & guest. Maybe later! */
-    return (isDnDCopyAction(uAction) ? (DragAndDropAction_T)DragAndDropAction_Copy :
-            isDnDMoveAction(uAction) ? (DragAndDropAction_T)DragAndDropAction_Move :
-            (DragAndDropAction_T)DragAndDropAction_Ignore);
-}
-
-/* static */
-void GuestDnDPrivate::toMainActions(uint32_t uActions,
-                                    ComSafeArrayOut(DragAndDropAction_T, actions))
-{
-    /* For now it doesn't seems useful to allow a
-     * link action between host & guest. Maybe later! */
-    RTCList<DragAndDropAction_T> list;
-    if (hasDnDCopyAction(uActions))
-        list.append(DragAndDropAction_Copy);
-    if (hasDnDMoveAction(uActions))
-        list.append(DragAndDropAction_Move);
-
-    com::SafeArray<DragAndDropAction_T> sfaActions(list.size());
-    for (size_t i = 0; i < list.size(); ++i)
-        sfaActions[i] = list.at(i);
-    sfaActions.detachTo(ComSafeArrayOutArg(actions));
-}
-
-GuestDnD::GuestDnD(const ComObjPtr<Guest>& pGuest)
-    : d_ptr(new GuestDnDPrivate(this, pGuest))
-{
-}
-
-GuestDnD::~GuestDnD(void)
-{
-    delete d_ptr;
-}
-
-HRESULT GuestDnD::dragHGEnter(ULONG uScreenId, ULONG uX, ULONG uY,
-                              DragAndDropAction_T defaultAction,
-                              ComSafeArrayIn(DragAndDropAction_T, allowedActions),
-                              ComSafeArrayIn(IN_BSTR, formats),
-                              DragAndDropAction_T *pResultAction)
-{
-    DPTR(GuestDnD);
-    const ComObjPtr<Guest> &p = d->p;
-
-    /* Default is ignoring */
-    *pResultAction = DragAndDropAction_Ignore;
-
-    /* Check & convert the drag & drop actions */
-    uint32_t uDefAction      = 0;
-    uint32_t uAllowedActions = 0;
-    d->toHGCMActions(defaultAction, &uDefAction, ComSafeArrayInArg(allowedActions), &uAllowedActions);
-    /* If there is no usable action, ignore this request. */
-    if (isDnDIgnoreAction(uDefAction))
-        return S_OK;
-
-    /* Make a flat data string out of the mime-type list. */
-    RTCString strFormats = d->toFormatString(ComSafeArrayInArg(formats));
-    /* If there is no valid mime-type, ignore this request. */
-    if (strFormats.isEmpty())
-        return S_OK;
-
-    HRESULT hr = S_OK;
-
-    try
-    {
-        /* Adjust the coordinates in a multi-monitor setup. */
-        d->adjustCoords(uScreenId, &uX, &uY);
-
-        VBOXHGCMSVCPARM paParms[7];
-        int i = 0;
-        paParms[i++].setUInt32(uScreenId);
-        paParms[i++].setUInt32(uX);
-        paParms[i++].setUInt32(uY);
-        paParms[i++].setUInt32(uDefAction);
-        paParms[i++].setUInt32(uAllowedActions);
-        paParms[i++].setPointer((void*)strFormats.c_str(), strFormats.length() + 1);
-        paParms[i++].setUInt32(strFormats.length() + 1);
-
-        d->hostCall(DragAndDropSvc::HOST_DND_HG_EVT_ENTER,
-                    i,
-                    paParms);
-
-        DnDGuestResponse *pResp = d->response();
-        if (pResp->waitForGuestResponse() == VERR_TIMEOUT)
-            return S_OK;
-
-        /* Copy the response info */
-        *pResultAction = d->toMainAction(pResp->defAction());
-        LogFlowFunc(("*pResultAction=%ld\n", *pResultAction));
-    }
-    catch (HRESULT hr2)
-    {
-        hr = hr2;
-    }
-
-    return hr;
-}
-
-HRESULT GuestDnD::dragHGMove(ULONG uScreenId, ULONG uX, ULONG uY,
-                             DragAndDropAction_T defaultAction,
-                             ComSafeArrayIn(DragAndDropAction_T, allowedActions),
-                             ComSafeArrayIn(IN_BSTR, formats),
-                             DragAndDropAction_T *pResultAction)
-{
-    DPTR(GuestDnD);
-    const ComObjPtr<Guest> &p = d->p;
-
-    /* Default is ignoring */
-    *pResultAction = DragAndDropAction_Ignore;
-
-    /* Check & convert the drag & drop actions */
-    uint32_t uDefAction      = 0;
-    uint32_t uAllowedActions = 0;
-    d->toHGCMActions(defaultAction, &uDefAction, ComSafeArrayInArg(allowedActions), &uAllowedActions);
-    /* If there is no usable action, ignore this request. */
-    if (isDnDIgnoreAction(uDefAction))
-        return S_OK;
-
-    /* Make a flat data string out of the mime-type list. */
-    RTCString strFormats = d->toFormatString(ComSafeArrayInArg(formats));
-    /* If there is no valid mime-type, ignore this request. */
-    if (strFormats.isEmpty())
-        return S_OK;
-
-    HRESULT hr = S_OK;
-
-    try
-    {
-        /* Adjust the coordinates in a multi-monitor setup. */
-        d->adjustCoords(uScreenId, &uX, &uY);
-
-        VBOXHGCMSVCPARM paParms[7];
-        int i = 0;
-        paParms[i++].setUInt32(uScreenId);
-        paParms[i++].setUInt32(uX);
-        paParms[i++].setUInt32(uY);
-        paParms[i++].setUInt32(uDefAction);
-        paParms[i++].setUInt32(uAllowedActions);
-        paParms[i++].setPointer((void*)strFormats.c_str(), strFormats.length() + 1);
-        paParms[i++].setUInt32(strFormats.length() + 1);
-
-        d->hostCall(DragAndDropSvc::HOST_DND_HG_EVT_MOVE,
-                    i,
-                    paParms);
-
-        DnDGuestResponse *pResp = d->response();
-        if (pResp->waitForGuestResponse() == VERR_TIMEOUT)
-            return S_OK;
-
-        /* Copy the response info */
-        *pResultAction = d->toMainAction(pResp->defAction());
-        LogFlowFunc(("*pResultAction=%ld\n", *pResultAction));
-    }
-    catch (HRESULT hr2)
-    {
-        hr = hr2;
-    }
-
-    return hr;
-}
-
-HRESULT GuestDnD::dragHGLeave(ULONG uScreenId)
-{
-    DPTR(GuestDnD);
-    const ComObjPtr<Guest> &p = d->p;
-
-    HRESULT hr = S_OK;
-
-    try
-    {
-        d->hostCall(DragAndDropSvc::HOST_DND_HG_EVT_LEAVE,
-                    0,
-                    NULL);
-
-        DnDGuestResponse *pResp = d->response();
-        pResp->waitForGuestResponse();
-    }
-    catch (HRESULT hr2)
-    {
-        hr = hr2;
-    }
-
-    return hr;
-}
-
-HRESULT GuestDnD::dragHGDrop(ULONG uScreenId, ULONG uX, ULONG uY,
-                             DragAndDropAction_T defaultAction,
-                             ComSafeArrayIn(DragAndDropAction_T, allowedActions),
-                             ComSafeArrayIn(IN_BSTR, formats),
-                             BSTR *pstrFormat,
-                             DragAndDropAction_T *pResultAction)
-{
-    DPTR(GuestDnD);
-    const ComObjPtr<Guest> &p = d->p;
-
-    /* Default is ignoring */
-    *pResultAction = DragAndDropAction_Ignore;
-
-    /* Check & convert the drag & drop actions */
-    uint32_t uDefAction      = 0;
-    uint32_t uAllowedActions = 0;
-    d->toHGCMActions(defaultAction, &uDefAction, ComSafeArrayInArg(allowedActions), &uAllowedActions);
-    /* If there is no usable action, ignore this request. */
-    if (isDnDIgnoreAction(uDefAction))
-        return S_OK;
-
-    /* Make a flat data string out of the mime-type list. */
-    RTCString strFormats = d->toFormatString(ComSafeArrayInArg(formats));
-    /* If there is no valid mime-type, ignore this request. */
-    if (strFormats.isEmpty())
-        return S_OK;
-
-    HRESULT hr = S_OK;
-
-    try
-    {
-        /* Adjust the coordinates in a multi-monitor setup. */
-        d->adjustCoords(uScreenId, &uX, &uY);
-
-        VBOXHGCMSVCPARM paParms[7];
-        int i = 0;
-        paParms[i++].setUInt32(uScreenId);
-        paParms[i++].setUInt32(uX);
-        paParms[i++].setUInt32(uY);
-        paParms[i++].setUInt32(uDefAction);
-        paParms[i++].setUInt32(uAllowedActions);
-        paParms[i++].setPointer((void*)strFormats.c_str(), strFormats.length() + 1);
-        paParms[i++].setUInt32(strFormats.length() + 1);
-
-        d->hostCall(DragAndDropSvc::HOST_DND_HG_EVT_DROPPED,
-                    i,
-                    paParms);
-
-        DnDGuestResponse *pResp = d->response();
-        if (pResp->waitForGuestResponse() == VERR_TIMEOUT)
-            return S_OK;
-
-        /* Get the resulting action from the guest. */
-        *pResultAction = d->toMainAction(pResp->defAction());
-
-        LogFlowFunc(("resFormat=%s, resAction=%RU32\n",
-                     pResp->format().c_str(), pResp->defAction()));
-
-        Bstr(pResp->format()).cloneTo(pstrFormat);
-    }
-    catch (HRESULT hr2)
-    {
-        hr = hr2;
-    }
-
-    return hr;
-}
-
-HRESULT GuestDnD::dragHGPutData(ULONG uScreenId, IN_BSTR bstrFormat,
-                                ComSafeArrayIn(BYTE, data), IProgress **ppProgress)
-{
-    DPTR(GuestDnD);
-    const ComObjPtr<Guest> &p = d->p;
-
-    HRESULT hr = S_OK;
-
-    try
-    {
-        Utf8Str strFormat(bstrFormat);
-        com::SafeArray<BYTE> sfaData(ComSafeArrayInArg(data));
-
-        VBOXHGCMSVCPARM paParms[5];
-        int i = 0;
-        paParms[i++].setUInt32(uScreenId);
-        paParms[i++].setPointer((void*)strFormat.c_str(), (uint32_t)strFormat.length() + 1);
-        paParms[i++].setUInt32((uint32_t)strFormat.length() + 1);
-        paParms[i++].setPointer((void*)sfaData.raw(), (uint32_t)sfaData.size());
-        paParms[i++].setUInt32((uint32_t)sfaData.size());
-
-        DnDGuestResponse *pResp = d->response();
-        /* Reset any old progress status. */
-        pResp->resetProgress(p);
-
-        /* Note: The actual data transfer of files/directoies is performed by the
-         *       DnD host service. */
-        d->hostCall(DragAndDropSvc::HOST_DND_HG_SND_DATA,
-                    i,
-                    paParms);
-
-        /* Query the progress object to the caller. */
-        pResp->queryProgressTo(ppProgress);
-    }
-    catch (HRESULT hr2)
-    {
-        hr = hr2;
-    }
-
-    return hr;
-}
-
-#ifdef VBOX_WITH_DRAG_AND_DROP_GH
-HRESULT GuestDnD::dragGHPending(ULONG uScreenId,
-                                ComSafeArrayOut(BSTR, formats),
-                                ComSafeArrayOut(DragAndDropAction_T, allowedActions),
-                                DragAndDropAction_T *pDefaultAction)
-{
-    DPTR(GuestDnD);
-    const ComObjPtr<Guest> &p = d->p;
-
-    /* Default is ignoring */
-    *pDefaultAction = DragAndDropAction_Ignore;
-
-    HRESULT hr = S_OK;
-
-    try
-    {
-        VBOXHGCMSVCPARM paParms[1];
-        int i = 0;
-        paParms[i++].setUInt32(uScreenId);
-
-        d->hostCall(DragAndDropSvc::HOST_DND_GH_REQ_PENDING,
-                    i,
-                    paParms);
-
-        DnDGuestResponse *pResp = d->response();
-        if (pResp->waitForGuestResponse() == VERR_TIMEOUT)
-            return S_OK;
-
-        if (isDnDIgnoreAction(pResp->defAction()))
-            return S_OK;
-
-        /* Fetch the default action to use. */
-        *pDefaultAction = d->toMainAction(pResp->defAction());
-        d->toFormatSafeArray(pResp->format(), ComSafeArrayOutArg(formats));
-        d->toMainActions(pResp->allActions(), ComSafeArrayOutArg(allowedActions));
-
-        LogFlowFunc(("*pDefaultAction=0x%x\n", *pDefaultAction));
-    }
-    catch (HRESULT hr2)
-    {
-        hr = hr2;
-    }
-
-    return hr;
-}
-
-HRESULT GuestDnD::dragGHDropped(IN_BSTR bstrFormat, DragAndDropAction_T action,
-                                IProgress **ppProgress)
-{
-    DPTR(GuestDnD);
-    const ComObjPtr<Guest> &p = d->p;
-
-    Utf8Str strFormat(bstrFormat);
-    HRESULT hr = S_OK;
-
-    uint32_t uAction = d->toHGCMAction(action);
-    /* If there is no usable action, ignore this request. */
-    if (isDnDIgnoreAction(uAction))
-        return S_OK;
-
-    const char *pcszFormat = strFormat.c_str();
-    bool fNeedsDropDir = DnDMIMENeedsDropDir(pcszFormat, strlen(pcszFormat));
-    LogFlowFunc(("strFormat=%s, uAction=0x%x, fNeedsDropDir=%RTbool\n",
-                 pcszFormat, uAction, fNeedsDropDir));
-
-    DnDGuestResponse *pResp = d->response();
-    AssertPtr(pResp);
-
-    /* Reset any old data. */
-    pResp->reset();
-    pResp->resetProgress(p);
-
-    /* Set the format we are going to retrieve to have it around
-     * when retrieving the data later. */
-    pResp->setFormat(strFormat);
-
-    if (fNeedsDropDir)
-    {
-        char szDropDir[RTPATH_MAX];
-        int rc = DnDDirCreateDroppedFiles(szDropDir, sizeof(szDropDir));
-        if (RT_FAILURE(rc))
-            return p->setError(VBOX_E_IPRT_ERROR,
-                               p->tr("Unable to create the temporary drag'n drop directory \"%s\" (%Rrc)\n"),
-                               szDropDir, rc);
-        LogFlowFunc(("Dropped files directory on the host is: %s\n", szDropDir));
-
-        pResp->setDropDir(szDropDir);
-    }
-
-    try
-    {
-        VBOXHGCMSVCPARM paParms[3];
-        int i = 0;
-        paParms[i++].setPointer((void*)strFormat.c_str(), (uint32_t)strFormat.length() + 1);
-        paParms[i++].setUInt32((uint32_t)strFormat.length() + 1);
-        paParms[i++].setUInt32(uAction);
-
-        d->hostCall(DragAndDropSvc::HOST_DND_GH_EVT_DROPPED,
-                    i,
-                    paParms);
-
-        /* Query the progress object to the caller. */
-        pResp->queryProgressTo(ppProgress);
-    }
-    catch (HRESULT hr2)
-    {
-        hr = hr2;
-    }
-
-    return hr;
-}
-
-HRESULT GuestDnD::dragGHGetData(ComSafeArrayOut(BYTE, data))
-{
-    DPTR(GuestDnD);
-    const ComObjPtr<Guest> &p = d->p;
-
-    HRESULT hr = S_OK;
-
-    DnDGuestResponse *pResp = d->response();
-    if (pResp)
-    {
-        com::SafeArray<BYTE> sfaData;
-
-        size_t cbData = pResp->size();
-        if (cbData)
-        {
-            const void *pvData = pResp->data();
-            AssertPtr(pvData);
-
-            Utf8Str strFormat = pResp->format();
-            LogFlowFunc(("strFormat=%s, cbData=%zu, pvData=0x%p\n",
-                         strFormat.c_str(), cbData, pvData));
-
-            if (DnDMIMEHasFileURLs(strFormat.c_str(), strFormat.length()))
-            {
-                LogFlowFunc(("strDropDir=%s\n", pResp->dropDir().c_str()));
-
-                DnDURIList lstURI;
-                int rc2 = lstURI.RootFromURIData(pvData, cbData, 0 /* fFlags */);
-                if (RT_SUCCESS(rc2))
-                {
-                    Utf8Str strURIs = lstURI.RootToString(pResp->dropDir());
-                    size_t cbURIs = strURIs.length();
-                    if (sfaData.resize(cbURIs + 1 /* Include termination */))
-                        memcpy(sfaData.raw(), strURIs.c_str(), cbURIs);
-                    else
-                        hr = E_OUTOFMEMORY;
-                }
-                else
-                    hr = VBOX_E_IPRT_ERROR;
-
-                LogFlowFunc(("Found %zu root URIs, rc=%Rrc\n", lstURI.RootCount(), rc2));
-            }
-            else
-            {
-                /* Copy the data into a safe array of bytes. */
-                if (sfaData.resize(cbData))
-                    memcpy(sfaData.raw(), pvData, cbData);
-                else
-                    hr = E_OUTOFMEMORY;
-            }
-        }
-
-        /* Detach in any case, regardless of data size. */
-        sfaData.detachTo(ComSafeArrayOutArg(data));
-
-        /* Delete the data. */
-        pResp->reset();
-    }
-    else
-        hr = VBOX_E_INVALID_OBJECT_STATE;
-
-    LogFlowFunc(("Returning hr=%Rhrc\n", hr));
-    return hr;
-}
-
-int GuestDnD::onGHSendData(DnDGuestResponse *pResp,
-                           const void *pvData, size_t cbData,
-                           size_t cbTotalSize)
-{
-    AssertPtrReturn(pResp, VERR_INVALID_POINTER);
-    AssertPtrReturn(pvData, VERR_INVALID_POINTER);
-    AssertReturn(cbData, VERR_INVALID_PARAMETER);
-    AssertReturn(cbTotalSize, VERR_INVALID_PARAMETER);
-
-    int rc = pResp->dataAdd(pvData, cbData, NULL /* Current size */);
-    if (RT_SUCCESS(rc))
-        rc = pResp->dataSetStatus(cbData, cbTotalSize);
-
-    LogFlowFuncLeaveRC(rc);
-    return rc;
-}
-
-int GuestDnD::onGHSendDir(DnDGuestResponse *pResp,
-                          const char *pszPath, size_t cbPath,
-                          uint32_t fMode)
-{
-    AssertPtrReturn(pResp, VERR_INVALID_POINTER);
-    AssertPtrReturn(pszPath, VERR_INVALID_POINTER);
-    AssertReturn(cbPath, VERR_INVALID_PARAMETER);
-
-    LogFlowFunc(("pszPath=%s, cbPath=%zu, fMode=0x%x\n",
-                 pszPath, cbPath, fMode));
-
-    int rc;
-    char *pszDir = RTPathJoinA(pResp->dropDir().c_str(), pszPath);
-    if (pszDir)
-    {
-        rc = RTDirCreateFullPath(pszDir, fMode);
-        RTStrFree(pszDir);
-    }
-    else
-        rc = VERR_NO_MEMORY;
-
-    if (RT_SUCCESS(rc))
-        rc = pResp->dataSetStatus(cbPath);
-
-    LogFlowFuncLeaveRC(rc);
-    return rc;
-}
-
-int GuestDnD::onGHSendFile(DnDGuestResponse *pResp,
-                           const char *pszPath, size_t cbPath,
-                           void *pvData, size_t cbData, uint32_t fMode)
-{
-    AssertPtrReturn(pResp, VERR_INVALID_POINTER);
-    AssertPtrReturn(pszPath, VERR_INVALID_POINTER);
-    AssertReturn(cbPath, VERR_INVALID_PARAMETER);
-
-    LogFlowFunc(("pszPath=%s, cbPath=%zu, fMode=0x%x\n",
-                 pszPath, cbPath, fMode));
-
-    int rc = pResp->writeToFile(pszPath, cbPath, pvData, cbData, fMode);
-
-    LogFlowFuncLeaveRC(rc);
-    return rc;
-}
-#endif /* VBOX_WITH_DRAG_AND_DROP_GH */
-
-/* static */
-DECLCALLBACK(int) GuestDnD::notifyGuestDragAndDropEvent(void *pvExtension, uint32_t u32Function,
-                                                        void *pvParms, uint32_t cbParms)
-{
-    LogFlowFunc(("pvExtension=%p, u32Function=%RU32, pvParms=%p, cbParms=%RU32\n",
-                 pvExtension, u32Function, pvParms, cbParms));
-
-    ComObjPtr<Guest> pGuest = reinterpret_cast<Guest*>(pvExtension);
-    if (!pGuest->m_pGuestDnD)
-        return VINF_SUCCESS;
-
-    GuestDnD *pGuestDnD = pGuest->m_pGuestDnD;
-    AssertPtr(pGuestDnD);
-
-    GuestDnDPrivate *d = static_cast<GuestDnDPrivate*>(pGuest->m_pGuestDnD->d_ptr);
-    const ComObjPtr<Guest> &p = d->p;
-
-    DnDGuestResponse *pResp = d->response();
-    if (pResp == NULL)
-        return VERR_INVALID_PARAMETER;
-
-    int rc = VINF_SUCCESS;
-    switch (u32Function)
-    {
-        case DragAndDropSvc::GUEST_DND_HG_ACK_OP:
-        {
-            DragAndDropSvc::PVBOXDNDCBHGACKOPDATA pCBData = reinterpret_cast<DragAndDropSvc::PVBOXDNDCBHGACKOPDATA>(pvParms);
-            AssertPtr(pCBData);
-            AssertReturn(sizeof(DragAndDropSvc::VBOXDNDCBHGACKOPDATA) == cbParms, VERR_INVALID_PARAMETER);
-            AssertReturn(DragAndDropSvc::CB_MAGIC_DND_HG_ACK_OP == pCBData->hdr.u32Magic, VERR_INVALID_PARAMETER);
-
-            pResp->setDefAction(pCBData->uAction);
-
-            rc = pResp->notifyAboutGuestResponse();
-            break;
-        }
-
-        case DragAndDropSvc::GUEST_DND_HG_REQ_DATA:
-        {
-            DragAndDropSvc::PVBOXDNDCBHGREQDATADATA pCBData = reinterpret_cast<DragAndDropSvc::PVBOXDNDCBHGREQDATADATA>(pvParms);
-            AssertPtr(pCBData);
-            AssertReturn(sizeof(DragAndDropSvc::VBOXDNDCBHGREQDATADATA) == cbParms, VERR_INVALID_PARAMETER);
-            AssertReturn(DragAndDropSvc::CB_MAGIC_DND_HG_REQ_DATA == pCBData->hdr.u32Magic, VERR_INVALID_PARAMETER);
-
-            pResp->setFormat(pCBData->pszFormat);
-
-            rc = pResp->notifyAboutGuestResponse();
-            break;
-        }
-
-        case DragAndDropSvc::GUEST_DND_HG_EVT_PROGRESS:
-        {
-            DragAndDropSvc::PVBOXDNDCBHGEVTPROGRESSDATA pCBData =
-                reinterpret_cast <DragAndDropSvc::PVBOXDNDCBHGEVTPROGRESSDATA>(pvParms);
-            AssertPtr(pCBData);
-            AssertReturn(sizeof(DragAndDropSvc::VBOXDNDCBHGEVTPROGRESSDATA) == cbParms, VERR_INVALID_PARAMETER);
-            AssertReturn(DragAndDropSvc::CB_MAGIC_DND_HG_EVT_PROGRESS == pCBData->hdr.u32Magic, VERR_INVALID_PARAMETER);
-
-            rc = pResp->setProgress(pCBData->uPercentage, pCBData->uState, pCBData->rc);
-            break;
-        }
-
-#ifdef VBOX_WITH_DRAG_AND_DROP_GH
-        case DragAndDropSvc::GUEST_DND_GH_ACK_PENDING:
-        {
-            DragAndDropSvc::PVBOXDNDCBGHACKPENDINGDATA pCBData =
-                reinterpret_cast <DragAndDropSvc::PVBOXDNDCBGHACKPENDINGDATA>(pvParms);
-            AssertPtr(pCBData);
-            AssertReturn(sizeof(DragAndDropSvc::VBOXDNDCBGHACKPENDINGDATA) == cbParms, VERR_INVALID_PARAMETER);
-            AssertReturn(DragAndDropSvc::CB_MAGIC_DND_GH_ACK_PENDING == pCBData->hdr.u32Magic, VERR_INVALID_PARAMETER);
-
-            pResp->setFormat(pCBData->pszFormat);
-            pResp->setDefAction(pCBData->uDefAction);
-            pResp->setAllActions(pCBData->uAllActions);
-
-            rc = pResp->notifyAboutGuestResponse();
-            break;
-        }
-
-        case DragAndDropSvc::GUEST_DND_GH_SND_DATA:
-        {
-            DragAndDropSvc::PVBOXDNDCBSNDDATADATA pCBData = reinterpret_cast<DragAndDropSvc::PVBOXDNDCBSNDDATADATA>(pvParms);
-            AssertPtr(pCBData);
-            AssertReturn(sizeof(DragAndDropSvc::VBOXDNDCBSNDDATADATA) == cbParms, VERR_INVALID_PARAMETER);
-            AssertReturn(DragAndDropSvc::CB_MAGIC_DND_GH_SND_DATA == pCBData->hdr.u32Magic, VERR_INVALID_PARAMETER);
-
-            rc = pGuestDnD->onGHSendData(pResp, pCBData->pvData, pCBData->cbData,
-                                         pCBData->cbTotalSize);
-            break;
-        }
-
-        case DragAndDropSvc::GUEST_DND_GH_SND_DIR:
-        {
-            DragAndDropSvc::PVBOXDNDCBSNDDIRDATA pCBData = reinterpret_cast<DragAndDropSvc::PVBOXDNDCBSNDDIRDATA>(pvParms);
-            AssertPtr(pCBData);
-            AssertReturn(sizeof(DragAndDropSvc::VBOXDNDCBSNDDIRDATA) == cbParms, VERR_INVALID_PARAMETER);
-            AssertReturn(DragAndDropSvc::CB_MAGIC_DND_GH_SND_DIR == pCBData->hdr.u32Magic, VERR_INVALID_PARAMETER);
-
-            rc = pGuestDnD->onGHSendDir(pResp, pCBData->pszPath, pCBData->cbPath, pCBData->fMode);
-            break;
-        }
-
-        case DragAndDropSvc::GUEST_DND_GH_SND_FILE:
-        {
-            DragAndDropSvc::PVBOXDNDCBSNDFILEDATA pCBData = reinterpret_cast<DragAndDropSvc::PVBOXDNDCBSNDFILEDATA>(pvParms);
-            AssertPtr(pCBData);
-            AssertReturn(sizeof(DragAndDropSvc::VBOXDNDCBSNDFILEDATA) == cbParms, VERR_INVALID_PARAMETER);
-            AssertReturn(DragAndDropSvc::CB_MAGIC_DND_GH_SND_FILE == pCBData->hdr.u32Magic, VERR_INVALID_PARAMETER);
-
-            rc = pGuestDnD->onGHSendFile(pResp, pCBData->pszFilePath, pCBData->cbFilePath,
-                                         pCBData->pvData, pCBData->cbData, pCBData->fMode);
-            break;
-        }
-
-        case DragAndDropSvc::GUEST_DND_GH_EVT_ERROR:
-        {
-            DragAndDropSvc::PVBOXDNDCBEVTERRORDATA pCBData = reinterpret_cast<DragAndDropSvc::PVBOXDNDCBEVTERRORDATA>(pvParms);
-            AssertPtr(pCBData);
-            AssertReturn(sizeof(DragAndDropSvc::VBOXDNDCBEVTERRORDATA) == cbParms, VERR_INVALID_PARAMETER);
-            AssertReturn(DragAndDropSvc::CB_MAGIC_DND_GH_EVT_ERROR == pCBData->hdr.u32Magic, VERR_INVALID_PARAMETER);
-
-            /* Cleanup. */
-            pResp->reset();
-            rc = pResp->setProgress(100, DragAndDropSvc::DND_PROGRESS_ERROR, pCBData->rc);
-            break;
-        }
-#endif /* VBOX_WITH_DRAG_AND_DROP_GH */
-        default:
-            rc = VERR_NOT_SUPPORTED; /* Tell the guest. */
-            break;
-    }
-
-    LogFlowFunc(("Returning rc=%Rrc\n", rc));
-    return rc;
-}
-#endif /* VBOX_WITH_DRAG_AND_DROP */
-
Index: trunk/src/VBox/Main/src-client/GuestDnDPrivate.cpp
===================================================================
--- trunk/src/VBox/Main/src-client/GuestDnDPrivate.cpp	(revision 51476)
+++ trunk/src/VBox/Main/src-client/GuestDnDPrivate.cpp	(revision 51476)
@@ -0,0 +1,845 @@
+/* $Id$ */
+/** @file
+ * Private guest drag and drop code, used by GuestDnDTarget +
+ * GuestDnDSource.
+ */
+
+/*
+ * Copyright (C) 2011-2014 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+#include "GuestImpl.h"
+#include "AutoCaller.h"
+
+#ifdef VBOX_WITH_DRAG_AND_DROP
+# include "ConsoleImpl.h"
+# include "ProgressImpl.h"
+# include "GuestDnDPrivate.h"
+
+# include <algorithm>
+
+# include <iprt/dir.h>
+# include <iprt/path.h>
+# include <iprt/stream.h>
+# include <iprt/semaphore.h>
+# include <iprt/cpp/utils.h>
+
+# include <VMMDev.h>
+
+# include <VBox/GuestHost/DragAndDrop.h>
+# include <VBox/HostServices/DragAndDropSvc.h>
+
+# ifdef LOG_GROUP
+#  undef LOG_GROUP
+# endif
+# define LOG_GROUP LOG_GROUP_GUEST_DND
+# include <VBox/log.h>
+
+/**
+ * Overview:
+ *
+ * Drag and Drop is handled over the internal HGCM service for the host <->
+ * guest communication. Beside that we need to map the Drag and Drop protocols
+ * of the various OS's we support to our internal channels, this is also highly
+ * communicative in both directions. Unfortunately HGCM isn't really designed
+ * for that. Next we have to foul some of the components. This includes to
+ * trick X11 on the guest side, but also Qt needs to be tricked on the host
+ * side a little bit.
+ *
+ * The following components are involved:
+ *
+ * 1. GUI: Uses the Qt classes for Drag and Drop and mainly forward the content
+ *    of it to the Main IGuest interface (see UIDnDHandler.cpp).
+ * 2. Main: Public interface for doing Drag and Drop. Also manage the IProgress
+ *    interfaces for blocking the caller by showing a progress dialog (see
+ *    this file).
+ * 3. HGCM service: Handle all messages from the host to the guest at once and
+ *    encapsulate the internal communication details (see dndmanager.cpp and
+ *    friends).
+ * 4. Guest additions: Split into the platform neutral part (see
+ *    VBoxGuestR3LibDragAndDrop.cpp) and the guest OS specific parts.
+ *    Receive/send message from/to the HGCM service and does all guest specific
+ *    operations. Currently only X11 is supported (see draganddrop.cpp within
+ *    VBoxClient).
+ *
+ * Host -> Guest:
+ * 1. There are DnD Enter, Move, Leave events which are send exactly like this
+ *    to the guest. The info includes the pos, mimetypes and allowed actions.
+ *    The guest has to respond with an action it would accept, so the GUI could
+ *    change the cursor.
+ * 2. On drop, first a drop event is sent. If this is accepted a drop data
+ *    event follows. This blocks the GUI and shows some progress indicator.
+ *
+ * Guest -> Host:
+ * 1. The GUI is asking the guest if a DnD event is pending when the user moves
+ *    the cursor out of the view window. If so, this returns the mimetypes and
+ *    allowed actions.
+ * (2. On every mouse move this is asked again, to make sure the DnD event is
+ *     still valid.)
+ * 3. On drop the host request the data from the guest. This blocks the GUI and
+ *    shows some progress indicator.
+ *
+ * Some hints:
+ * m_strSupportedFormats here in this file defines the allowed mime-types.
+ * This is necessary because we need special handling for some of the
+ * mime-types. E.g. for URI lists we need to transfer the actual dirs and
+ * files. Text EOL may to be changed. Also unknown mime-types may need special
+ * handling as well, which may lead to undefined behavior in the host/guest, if
+ * not done.
+ *
+ * Dropping of a directory, means recursively transferring _all_ the content.
+ *
+ * Directories and files are placed into the user's temporary directory on the
+ * guest (e.g. /tmp/VirtualBox Dropped Files). We can't delete them after the
+ * DnD operation, because we didn't know what the DnD target does with it. E.g.
+ * it could just be opened in place. This could lead ofc to filling up the disk
+ * within the guest. To inform the user about this, a small app could be
+ * developed which scans this directory regularly and inform the user with a
+ * tray icon hint (and maybe the possibility to clean this up instantly). The
+ * same has to be done in the G->H direction when it is implemented.
+ *
+ * Of course only regularly files are supported. Symlinks are resolved and
+ * transfered as regularly files. First we don't know if the other side support
+ * symlinks at all and second they could point to somewhere in a directory tree
+ * which not exists on the other side.
+ *
+ * The code tries to preserve the file modes of the transfered dirs/files. This
+ * is useful (and maybe necessary) for two things:
+ * 1. If a file is executable, it should be also after the transfer, so the
+ *    user can just execute it, without manually tweaking the modes first.
+ * 2. If a dir/file is not accessible by group/others in the host, it shouldn't
+ *    be in the guest.
+ * In any case, the user mode is always set to rwx (so that we can access it
+ * ourself, in e.g. for a cleanup case after cancel).
+ *
+ * Cancel is supported in both directions and cleans up all previous steps
+ * (thats is: deleting already transfered dirs/files).
+ *
+ * In general I propose the following changes in the VBox HGCM infrastructure
+ * for the future:
+ * - Currently it isn't really possible to send messages to the guest from the
+ *   host. The host informs the guest just that there is something, the guest
+ *   than has to ask which message and depending on that send the appropriate
+ *   message to the host, which is filled with the right data.
+ * - There is no generic interface for sending bigger memory blocks to/from the
+ *   guest. This is now done here, but I guess was also necessary for e.g.
+ *   guest execution. So something generic which brake this up into smaller
+ *   blocks and send it would be nice (with all the error handling and such
+ *   ofc).
+ * - I developed a "protocol" for the DnD communication here. So the host and
+ *   the guest have always to match in the revision. This is ofc bad, because
+ *   the additions could be outdated easily. So some generic protocol number
+ *   support in HGCM for asking the host and the guest of the support version,
+ *   would be nice. Ofc at least the host should be able to talk to the guest,
+ *   even when the version is below the host one.
+ * All this stuff would be useful for the current services, but also for future
+ * onces.
+ *
+ ** @todo
+ * - ESC doesn't really work (on Windows guests it's already implemented)
+ *   ... in any case it seems a little bit difficult to handle from the Qt
+ *   side. Maybe also a host specific implementation becomes necessary ...
+ *   this would be really worst ofc.
+ * - Add support for more mime-types (especially images, csv)
+ * - Test unusual behavior:
+ *   - DnD service crash in the guest during a DnD op (e.g. crash of VBoxClient or X11)
+ *   - Not expected order of the events between HGCM and the guest
+ * - Security considerations: We transfer a lot of memory between the guest and
+ *   the host and even allow the creation of dirs/files. Maybe there should be
+ *   limits introduced to preventing DOS attacks or filling up all the memory
+ *   (both in the host and the guest).
+ */
+
+GuestDnDResponse::GuestDnDResponse(const ComObjPtr<Guest>& pGuest)
+    : m_EventSem(NIL_RTSEMEVENT)
+    , m_defAction(0)
+    , m_allActions(0)
+    , m_pvData(0)
+    , m_cbData(0)
+    , m_cbDataCurrent(0)
+    , m_cbDataTotal(0)
+    , m_hFile(NIL_RTFILE)
+    , m_parent(pGuest)
+{
+    int rc = RTSemEventCreate(&m_EventSem);
+    AssertRC(rc);
+}
+
+GuestDnDResponse::~GuestDnDResponse(void)
+{
+    reset();
+
+    int rc = RTSemEventDestroy(m_EventSem);
+    AssertRC(rc);
+}
+
+int GuestDnDResponse::dataAdd(const void *pvData, uint32_t cbData,
+                              uint32_t *pcbCurSize)
+{
+    AssertPtrReturn(pvData, VERR_INVALID_POINTER);
+    AssertReturn(cbData, VERR_INVALID_PARAMETER);
+    /* pcbCurSize is optional. */
+
+    int rc = VINF_SUCCESS;
+
+    /** @todo Make reallocation scheme a bit smarter here. */
+    m_pvData = RTMemRealloc(m_pvData, m_cbData + cbData);
+    if (m_pvData)
+    {
+        memcpy(&static_cast<uint8_t*>(m_pvData)[m_cbData],
+               pvData, cbData);
+        m_cbData += cbData;
+
+        if (pcbCurSize)
+            *pcbCurSize = m_cbData;
+    }
+    else
+        rc = VERR_NO_MEMORY;
+
+    return rc;
+}
+
+/* static */
+Utf8Str GuestDnDResponse::errorToString(const ComObjPtr<Guest>& pGuest, int guestRc)
+{
+    Utf8Str strError;
+
+    switch (guestRc)
+    {
+        case VERR_ACCESS_DENIED:
+            strError += Utf8StrFmt(pGuest->tr("For one or more guest files or directories selected for transferring to the host your guest "
+                                              "user does not have the appropriate access rights for. Please make sure that all selected "
+                                              "elements can be accessed and that your guest user has the appropriate rights."));
+            break;
+
+        case VERR_NOT_FOUND:
+            /* Should not happen due to file locking on the guest, but anyway ... */
+            strError += Utf8StrFmt(pGuest->tr("One or more guest files or directories selected for transferring to the host were not"
+                                              "found on the guest anymore. This can be the case if the guest files were moved and/or"
+                                              "altered while the drag'n drop operation was in progress."));
+            break;
+
+        case VERR_SHARING_VIOLATION:
+            strError += Utf8StrFmt(pGuest->tr("One or more guest files or directories selected for transferring to the host were locked. "
+                                              "Please make sure that all selected elements can be accessed and that your guest user has "
+                                              "the appropriate rights."));
+            break;
+
+        default:
+            strError += Utf8StrFmt("Drag'n drop guest error (%Rrc)", guestRc);
+            break;
+    }
+
+    return strError;
+}
+
+int GuestDnDResponse::notifyAboutGuestResponse(void)
+{
+    return RTSemEventSignal(m_EventSem);
+}
+
+void GuestDnDResponse::reset(void)
+{
+    LogFlowThisFuncEnter();
+
+    m_defAction = 0;
+    m_allActions = 0;
+
+    m_strDropDir = "";
+    m_strFormat = "";
+
+    if (m_pvData)
+    {
+        RTMemFree(m_pvData);
+        m_pvData = NULL;
+    }
+    m_cbData = 0;
+    m_cbDataCurrent = 0;
+    m_cbDataTotal = 0;
+
+    if (m_hFile != NIL_RTFILE)
+    {
+        RTFileClose(m_hFile);
+        m_hFile = NIL_RTFILE;
+    }
+    m_strFile = "";
+}
+
+HRESULT GuestDnDResponse::resetProgress(const ComObjPtr<Guest>& pParent)
+{
+    m_progress.setNull();
+    HRESULT rc = m_progress.createObject();
+    if (SUCCEEDED(rc))
+    {
+        rc = m_progress->init(static_cast<IGuest*>(pParent),
+                              Bstr(pParent->tr("Dropping data")).raw(),
+                              TRUE);
+    }
+    return rc;
+}
+
+int GuestDnDResponse::setProgress(unsigned uPercentage,
+                                  uint32_t uState, int rcOp /* = VINF_SUCCESS */)
+{
+    LogFlowFunc(("uPercentage=%RU32, uState=%RU32, rcOp=%Rrc\n",
+                 uPercentage, uState, rcOp));
+
+    int vrc = VINF_SUCCESS;
+    if (!m_progress.isNull())
+    {
+        BOOL fCompleted;
+        HRESULT hr = m_progress->COMGETTER(Completed)(&fCompleted);
+        if (!fCompleted)
+        {
+            if (uState == DragAndDropSvc::DND_PROGRESS_ERROR)
+            {
+                hr = m_progress->i_notifyComplete(VBOX_E_IPRT_ERROR,
+                                                  COM_IIDOF(IGuest),
+                                                  m_parent->getComponentName(),
+                                                  GuestDnDResponse::errorToString(m_parent, rcOp).c_str());
+                reset();
+            }
+            else if (uState == DragAndDropSvc::DND_PROGRESS_CANCELLED)
+            {
+                hr = m_progress->Cancel();
+                if (SUCCEEDED(hr))
+                    vrc = VERR_CANCELLED;
+
+                reset();
+            }
+            else /* uState == DragAndDropSvc::DND_PROGRESS_RUNNING */
+            {
+                hr = m_progress->SetCurrentOperationProgress(uPercentage);
+                AssertComRC(hr);
+                if (   uState      == DragAndDropSvc::DND_PROGRESS_COMPLETE
+                    || uPercentage >= 100)
+                    hr = m_progress->i_notifyComplete(S_OK);
+            }
+        }
+    }
+
+    return vrc;
+}
+
+int GuestDnDResponse::dataSetStatus(size_t cbDataAdd, size_t cbDataTotal /* = 0 */)
+{
+    if (cbDataTotal)
+    {
+#ifndef DEBUG_andy
+        AssertMsg(m_cbDataTotal <= cbDataTotal, ("New data size must not be smaller (%zu) than old value (%zu)\n",
+                                                 cbDataTotal, m_cbDataTotal));
+#endif
+        LogFlowFunc(("Updating total data size from %zu to %zu\n", m_cbDataTotal, cbDataTotal));
+        m_cbDataTotal = cbDataTotal;
+    }
+    AssertMsg(m_cbDataTotal, ("m_cbDataTotal must not be <= 0\n"));
+
+    m_cbDataCurrent += cbDataAdd;
+    unsigned int cPercentage = RT_MIN(m_cbDataCurrent * 100.0 / m_cbDataTotal, 100);
+
+    /** @todo Don't use anonymous enums (uint32_t). */
+    uint32_t uStatus = DragAndDropSvc::DND_PROGRESS_RUNNING;
+    if (m_cbDataCurrent >= m_cbDataTotal)
+        uStatus = DragAndDropSvc::DND_PROGRESS_COMPLETE;
+
+#ifdef DEBUG_andy
+    LogFlowFunc(("Updating transfer status (%zu/%zu), status=%ld\n",
+                 m_cbDataCurrent, m_cbDataTotal, uStatus));
+#else
+    AssertMsg(m_cbDataCurrent <= m_cbDataTotal,
+              ("More data transferred (%zu) than initially announced (%zu), cbDataAdd=%zu\n",
+              m_cbDataCurrent, m_cbDataTotal, cbDataAdd));
+#endif
+    int rc = setProgress(cPercentage, uStatus);
+
+    /** @todo For now we instantly confirm the cancel. Check if the
+     *        guest should first clean up stuff itself and than really confirm
+     *        the cancel request by an extra message. */
+    if (rc == VERR_CANCELLED)
+        rc = setProgress(100, DragAndDropSvc::DND_PROGRESS_CANCELLED);
+
+    LogFlowFuncLeaveRC(rc);
+    return rc;
+}
+
+HRESULT GuestDnDResponse::queryProgressTo(IProgress **ppProgress)
+{
+    return m_progress.queryInterfaceTo(ppProgress);
+}
+
+int GuestDnDResponse::waitForGuestResponse(RTMSINTERVAL msTimeout /*= 500 */)
+{
+    int rc = RTSemEventWait(m_EventSem, msTimeout);
+#ifdef DEBUG_andy
+    LogFlowFunc(("msTimeout=%RU32, rc=%Rrc\n", msTimeout, rc));
+#endif
+    return rc;
+}
+
+int GuestDnDResponse::writeToFile(const char *pszPath, size_t cbPath,
+                                  void *pvData, size_t cbData, uint32_t fMode)
+{
+    /** @todo Support locking more than one file at a time! We
+     *        might want to have a table in DnDGuestImpl which
+     *        keeps those file pointers around, or extend the
+     *        actual protocol for explicit open calls.
+     *
+     *        For now we only keep one file open at a time, so if
+     *        a client does alternating writes to different files
+     *        this function will close the old and re-open the new
+     *        file on every call. */
+    int rc;
+    if (   m_hFile == NIL_RTFILE
+        || m_strFile != pszPath)
+    {
+        char *pszFile = RTPathJoinA(m_strDropDir.c_str(), pszPath);
+        if (pszFile)
+        {
+            RTFILE hFile;
+            /** @todo Respect fMode!  */
+            rc = RTFileOpen(&hFile, pszFile,
+                              RTFILE_O_OPEN_CREATE | RTFILE_O_DENY_WRITE
+                            | RTFILE_O_WRITE | RTFILE_O_APPEND);
+            if (RT_SUCCESS(rc))
+            {
+                LogFlowFunc(("Opening \"%s\" (fMode=0x%x) for writing ...\n",
+                             pszFile, fMode));
+
+                m_hFile = hFile;
+                m_strFile = pszPath;
+            }
+
+            RTStrFree(pszFile);
+        }
+        else
+            rc = VERR_NO_MEMORY;
+    }
+    else
+        rc = VINF_SUCCESS;
+
+    if (RT_SUCCESS(rc))
+    {
+        rc = RTFileWrite(m_hFile, pvData, cbData,
+                         NULL /* No partial writes */);
+
+        if (RT_SUCCESS(rc))
+            rc = dataSetStatus(cbData);
+    }
+
+    return rc;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+GuestDnD* GuestDnD::s_pInstance = NULL;
+
+GuestDnD::GuestDnD(const ComObjPtr<Guest> &pGuest)
+    : m_pGuest(pGuest)
+{
+    LogFlowFuncEnter();
+
+    m_pResponse = new GuestDnDResponse(pGuest);
+
+    /* List of supported MIME types.
+     * Note: If you add something here, make sure you test it with all supported guest OSes!
+     ** @todo Make this MIME list configurable / extendable (by extra data?). Currently
+     *        this is done hardcoded on every guest platform (*NIX/Windows).
+     */
+    const com::Utf8Str arrEntries[] = {
+        "text/uri-list",
+        /* Text */
+        "text/plain;charset=utf-8",
+        "UTF8_STRING",
+        "text/plain",
+        "COMPOUND_TEXT",
+        "TEXT",
+        "STRING",
+        /* OpenOffice formats */
+        "application/x-openoffice-embed-source-xml;windows_formatname=\"Star Embed Source (XML)\"",
+        "application/x-openoffice-drawing;windows_formatname=\"Drawing Format\"",
+    };
+
+    for (size_t i = 0; i < RT_ELEMENTS(arrEntries); i++)
+        m_strSupportedFormats.push_back(arrEntries[0]);
+}
+
+GuestDnD::~GuestDnD(void)
+{
+    LogFlowFuncEnter();
+
+    if (m_pResponse)
+        delete m_pResponse;
+}
+
+int GuestDnD::adjustScreenCoordinates(ULONG uScreenId, ULONG *puX, ULONG *puY) const
+{
+    /** @todo r=andy Save the current screen's shifting coordinates to speed things up.
+     *               Only query for new offsets when the screen ID has changed. */
+
+    /* For multi-monitor support we need to add shift values to the coordinates
+     * (depending on the screen number). */
+    ComObjPtr<Console> pConsole = m_pGuest->getConsole();
+    ComPtr<IDisplay> pDisplay;
+    HRESULT hr = pConsole->COMGETTER(Display)(pDisplay.asOutParam());
+    if (FAILED(hr))
+        return hr;
+
+    LONG xShift, yShift;
+    hr = pDisplay->GetScreenResolution(uScreenId, NULL, NULL, NULL,
+                                       &xShift, &yShift);
+    if (FAILED(hr))
+        return hr;
+
+    if (puX)
+        *puX += xShift;
+    if (puY)
+        *puY += yShift;
+
+#ifdef DEBUG_andy
+    LogFlowFunc(("uScreenId=%RU32, x=%RU32, y=%RU32\n",
+                 uScreenId, puX ? *puX : 0, puY ? *puY : 0));
+#endif
+    return VINF_SUCCESS;
+}
+
+int GuestDnD::hostCall(uint32_t u32Function, uint32_t cParms, PVBOXHGCMSVCPARM paParms) const
+{
+    Assert(!m_pGuest.isNull());
+    ComObjPtr<Console> pConsole = m_pGuest->getConsole();
+
+    /* Forward the information to the VMM device. */
+    Assert(!pConsole.isNull());
+    VMMDev *pVMMDev = pConsole->getVMMDev();
+    if (!pVMMDev)
+        return VERR_COM_OBJECT_NOT_FOUND;
+
+    int rc = pVMMDev->hgcmHostCall("VBoxDragAndDropSvc", u32Function,
+                                   cParms, paParms);
+    LogFlowFunc(("uMsg=%RU32, cParms=%RU32, rc=%Rrc\n",
+                 u32Function, cParms, rc));
+    return rc;
+}
+
+/* static */
+com::Utf8Str GuestDnD::toFormatString(const std::vector<com::Utf8Str> &lstSupportedFormats,
+                                      const std::vector<com::Utf8Str> &lstFormats)
+{
+    com::Utf8Str strFormat;
+    for (size_t i = 0; i < lstFormats.size(); ++i)
+    {
+        const com::Utf8Str &f = lstFormats.at(i);
+        /* Only keep allowed format types. */
+        if (std::find(lstSupportedFormats.begin(),
+                      lstSupportedFormats.end(), f) != lstSupportedFormats.end())
+            strFormat += f + "\r\n";
+    }
+
+    return strFormat;
+}
+
+/* static */
+void GuestDnD::toFormatVector(const std::vector<com::Utf8Str> &lstSupportedFormats,
+                              const com::Utf8Str &strFormats,
+                              std::vector<com::Utf8Str> &vecformats)
+{
+    RTCList<RTCString> lstFormats = strFormats.split("\r\n");
+    size_t i = 0;
+    while (i < lstFormats.size())
+    {
+        /* Only keep allowed format types. */
+        if (std::find(lstSupportedFormats.begin(),
+                      lstSupportedFormats.end(), lstFormats.at(i)) == lstSupportedFormats.end())
+            lstFormats.removeAt(i);
+        else
+            ++i;
+    }
+
+    for (i = 0; i < lstFormats.size(); i++)
+    {
+        const Utf8Str &f = lstFormats.at(i);
+        if (std::find(lstSupportedFormats.begin(),
+                      lstSupportedFormats.end(), f) != lstSupportedFormats.end())
+            vecformats.push_back(lstFormats[i]);
+    }
+}
+
+/* static */
+uint32_t GuestDnD::toHGCMAction(DnDAction_T enmAction)
+{
+    uint32_t uAction = DND_IGNORE_ACTION;
+    switch (enmAction)
+    {
+        case DnDAction_Copy:
+            uAction = DND_COPY_ACTION;
+            break;
+        case DnDAction_Move:
+            uAction = DND_MOVE_ACTION;
+            break;
+        case DnDAction_Link:
+            /* For now it doesn't seems useful to allow a link
+               action between host & guest. Later? */
+        case DnDAction_Ignore:
+            /* Ignored. */
+            break;
+        default:
+            AssertMsgFailed(("Action %RU32 not recognized!\n", enmAction));
+            break;
+    }
+
+    return uAction;
+}
+
+/* static */
+void GuestDnD::toHGCMActions(DnDAction_T enmDefAction,
+                             uint32_t *puDefAction,
+                             const std::vector<DnDAction_T> vecAllowedActions,
+                             uint32_t *puAllowedActions)
+{
+    if (puDefAction)
+        *puDefAction = toHGCMAction(enmDefAction);
+    if (puAllowedActions)
+    {
+        *puAllowedActions = DND_IGNORE_ACTION;
+
+        /* First convert the allowed actions to a bit array. */
+        for (size_t i = 0; i < vecAllowedActions.size(); ++i)
+            *puAllowedActions |= toHGCMAction(vecAllowedActions[i]);
+
+        /* Second check if the default action is a valid action and if not so try
+         * to find an allowed action. */
+        if (isDnDIgnoreAction(*puAllowedActions))
+        {
+            if (hasDnDCopyAction(*puAllowedActions))
+                *puAllowedActions = DND_COPY_ACTION;
+            else if (hasDnDMoveAction(*puAllowedActions))
+                *puAllowedActions = DND_MOVE_ACTION;
+        }
+    }
+}
+
+/* static */
+DnDAction_T GuestDnD::toMainAction(uint32_t uAction)
+{
+    /* For now it doesn't seems useful to allow a
+     * link action between host & guest. Maybe later! */
+    return (isDnDCopyAction(uAction) ? (DnDAction_T)DnDAction_Copy :
+            isDnDMoveAction(uAction) ? (DnDAction_T)DnDAction_Move :
+            (DnDAction_T)DnDAction_Ignore);
+}
+
+/* static */
+void GuestDnD::toMainActions(uint32_t uActions,
+                             std::vector<DnDAction_T> &vecActions)
+{
+    /* For now it doesn't seems useful to allow a
+     * link action between host & guest. Maybe later! */
+    RTCList<DnDAction_T> lstActions;
+    if (hasDnDCopyAction(uActions))
+        lstActions.append(DnDAction_Copy);
+    if (hasDnDMoveAction(uActions))
+        lstActions.append(DnDAction_Move);
+
+    for (size_t i = 0; i < lstActions.size(); ++i)
+        vecActions.push_back(lstActions.at(i));
+}
+
+/* static */
+DECLCALLBACK(int) GuestDnD::notifyDnDDispatcher(void *pvExtension, uint32_t u32Function,
+                                                void *pvParms, uint32_t cbParms)
+{
+    LogFlowFunc(("pvExtension=%p, u32Function=%RU32, pvParms=%p, cbParms=%RU32\n",
+                 pvExtension, u32Function, pvParms, cbParms));
+
+    GuestDnD *pGuestDnD = reinterpret_cast<GuestDnD*>(pvExtension);
+    AssertPtrReturn(pGuestDnD, VERR_INVALID_POINTER);
+
+    GuestDnDResponse *pResp = pGuestDnD->m_pResponse;
+    AssertPtrReturn(pResp, VERR_INVALID_POINTER);
+
+    int rc;
+    switch (u32Function)
+    {
+        case DragAndDropSvc::GUEST_DND_HG_ACK_OP:
+        {
+            DragAndDropSvc::PVBOXDNDCBHGACKOPDATA pCBData = reinterpret_cast<DragAndDropSvc::PVBOXDNDCBHGACKOPDATA>(pvParms);
+            AssertPtr(pCBData);
+            AssertReturn(sizeof(DragAndDropSvc::VBOXDNDCBHGACKOPDATA) == cbParms, VERR_INVALID_PARAMETER);
+            AssertReturn(DragAndDropSvc::CB_MAGIC_DND_HG_ACK_OP == pCBData->hdr.u32Magic, VERR_INVALID_PARAMETER);
+
+            pResp->setDefAction(pCBData->uAction);
+
+            rc = pResp->notifyAboutGuestResponse();
+            break;
+        }
+
+        case DragAndDropSvc::GUEST_DND_HG_REQ_DATA:
+        {
+            DragAndDropSvc::PVBOXDNDCBHGREQDATADATA pCBData = reinterpret_cast<DragAndDropSvc::PVBOXDNDCBHGREQDATADATA>(pvParms);
+            AssertPtr(pCBData);
+            AssertReturn(sizeof(DragAndDropSvc::VBOXDNDCBHGREQDATADATA) == cbParms, VERR_INVALID_PARAMETER);
+            AssertReturn(DragAndDropSvc::CB_MAGIC_DND_HG_REQ_DATA == pCBData->hdr.u32Magic, VERR_INVALID_PARAMETER);
+
+            pResp->setFormat(pCBData->pszFormat);
+
+            rc = pResp->notifyAboutGuestResponse();
+            break;
+        }
+
+        case DragAndDropSvc::GUEST_DND_HG_EVT_PROGRESS:
+        {
+            DragAndDropSvc::PVBOXDNDCBHGEVTPROGRESSDATA pCBData =
+                reinterpret_cast <DragAndDropSvc::PVBOXDNDCBHGEVTPROGRESSDATA>(pvParms);
+            AssertPtr(pCBData);
+            AssertReturn(sizeof(DragAndDropSvc::VBOXDNDCBHGEVTPROGRESSDATA) == cbParms, VERR_INVALID_PARAMETER);
+            AssertReturn(DragAndDropSvc::CB_MAGIC_DND_HG_EVT_PROGRESS == pCBData->hdr.u32Magic, VERR_INVALID_PARAMETER);
+
+            rc = pResp->setProgress(pCBData->uPercentage, pCBData->uState, pCBData->rc);
+            break;
+        }
+
+# ifdef VBOX_WITH_DRAG_AND_DROP_GH
+        case DragAndDropSvc::GUEST_DND_GH_ACK_PENDING:
+        {
+            DragAndDropSvc::PVBOXDNDCBGHACKPENDINGDATA pCBData =
+                reinterpret_cast <DragAndDropSvc::PVBOXDNDCBGHACKPENDINGDATA>(pvParms);
+            AssertPtr(pCBData);
+            AssertReturn(sizeof(DragAndDropSvc::VBOXDNDCBGHACKPENDINGDATA) == cbParms, VERR_INVALID_PARAMETER);
+            AssertReturn(DragAndDropSvc::CB_MAGIC_DND_GH_ACK_PENDING == pCBData->hdr.u32Magic, VERR_INVALID_PARAMETER);
+
+            pResp->setFormat(pCBData->pszFormat);
+            pResp->setDefAction(pCBData->uDefAction);
+            pResp->setAllActions(pCBData->uAllActions);
+
+            rc = pResp->notifyAboutGuestResponse();
+            break;
+        }
+
+        case DragAndDropSvc::GUEST_DND_GH_SND_DATA:
+        {
+            DragAndDropSvc::PVBOXDNDCBSNDDATADATA pCBData = reinterpret_cast<DragAndDropSvc::PVBOXDNDCBSNDDATADATA>(pvParms);
+            AssertPtr(pCBData);
+            AssertReturn(sizeof(DragAndDropSvc::VBOXDNDCBSNDDATADATA) == cbParms, VERR_INVALID_PARAMETER);
+            AssertReturn(DragAndDropSvc::CB_MAGIC_DND_GH_SND_DATA == pCBData->hdr.u32Magic, VERR_INVALID_PARAMETER);
+
+            rc = pGuestDnD->onGHSendData(pResp, pCBData->pvData, pCBData->cbData,
+                                         pCBData->cbTotalSize);
+            break;
+        }
+
+        case DragAndDropSvc::GUEST_DND_GH_SND_DIR:
+        {
+            DragAndDropSvc::PVBOXDNDCBSNDDIRDATA pCBData = reinterpret_cast<DragAndDropSvc::PVBOXDNDCBSNDDIRDATA>(pvParms);
+            AssertPtr(pCBData);
+            AssertReturn(sizeof(DragAndDropSvc::VBOXDNDCBSNDDIRDATA) == cbParms, VERR_INVALID_PARAMETER);
+            AssertReturn(DragAndDropSvc::CB_MAGIC_DND_GH_SND_DIR == pCBData->hdr.u32Magic, VERR_INVALID_PARAMETER);
+
+            rc = pGuestDnD->onGHSendDir(pResp, pCBData->pszPath, pCBData->cbPath, pCBData->fMode);
+            break;
+        }
+
+        case DragAndDropSvc::GUEST_DND_GH_SND_FILE:
+        {
+            DragAndDropSvc::PVBOXDNDCBSNDFILEDATA pCBData = reinterpret_cast<DragAndDropSvc::PVBOXDNDCBSNDFILEDATA>(pvParms);
+            AssertPtr(pCBData);
+            AssertReturn(sizeof(DragAndDropSvc::VBOXDNDCBSNDFILEDATA) == cbParms, VERR_INVALID_PARAMETER);
+            AssertReturn(DragAndDropSvc::CB_MAGIC_DND_GH_SND_FILE == pCBData->hdr.u32Magic, VERR_INVALID_PARAMETER);
+
+            rc = pGuestDnD->onGHSendFile(pResp, pCBData->pszFilePath, pCBData->cbFilePath,
+                                         pCBData->pvData, pCBData->cbData, pCBData->fMode);
+            break;
+        }
+
+        case DragAndDropSvc::GUEST_DND_GH_EVT_ERROR:
+        {
+            DragAndDropSvc::PVBOXDNDCBEVTERRORDATA pCBData = reinterpret_cast<DragAndDropSvc::PVBOXDNDCBEVTERRORDATA>(pvParms);
+            AssertPtr(pCBData);
+            AssertReturn(sizeof(DragAndDropSvc::VBOXDNDCBEVTERRORDATA) == cbParms, VERR_INVALID_PARAMETER);
+            AssertReturn(DragAndDropSvc::CB_MAGIC_DND_GH_EVT_ERROR == pCBData->hdr.u32Magic, VERR_INVALID_PARAMETER);
+
+            /* Cleanup. */
+            pResp->reset();
+            rc = pResp->setProgress(100, DragAndDropSvc::DND_PROGRESS_ERROR, pCBData->rc);
+            break;
+        }
+# endif /* VBOX_WITH_DRAG_AND_DROP_GH */
+        default:
+            rc = VERR_NOT_SUPPORTED; /* Tell the guest. */
+            break;
+    }
+
+    LogFlowFunc(("Returning rc=%Rrc\n", rc));
+    return rc;
+}
+
+# ifdef VBOX_WITH_DRAG_AND_DROP_GH
+int GuestDnD::onGHSendData(GuestDnDResponse *pResp,
+                           const void *pvData, size_t cbData, size_t cbTotalSize)
+{
+    AssertPtrReturn(pResp, VERR_INVALID_POINTER);
+    AssertPtrReturn(pvData, VERR_INVALID_POINTER);
+    AssertReturn(cbData, VERR_INVALID_PARAMETER);
+    AssertReturn(cbTotalSize, VERR_INVALID_PARAMETER);
+
+    int rc = pResp->dataAdd(pvData, cbData, NULL /* Current size */);
+    if (RT_SUCCESS(rc))
+        rc = pResp->dataSetStatus(cbData, cbTotalSize);
+
+    LogFlowFuncLeaveRC(rc);
+    return rc;
+}
+
+int GuestDnD::onGHSendDir(GuestDnDResponse *pResp,
+                          const char *pszPath, size_t cbPath, uint32_t fMode)
+{
+    AssertPtrReturn(pResp, VERR_INVALID_POINTER);
+    AssertPtrReturn(pszPath, VERR_INVALID_POINTER);
+    AssertReturn(cbPath, VERR_INVALID_PARAMETER);
+
+    LogFlowFunc(("pszPath=%s, cbPath=%zu, fMode=0x%x\n",
+                 pszPath, cbPath, fMode));
+
+    int rc;
+    char *pszDir = RTPathJoinA(pResp->dropDir().c_str(), pszPath);
+    if (pszDir)
+    {
+        rc = RTDirCreateFullPath(pszDir, fMode);
+        RTStrFree(pszDir);
+    }
+    else
+        rc = VERR_NO_MEMORY;
+
+    if (RT_SUCCESS(rc))
+        rc = pResp->dataSetStatus(cbPath);
+
+    LogFlowFuncLeaveRC(rc);
+    return rc;
+}
+
+int GuestDnD::onGHSendFile(GuestDnDResponse *pResp,
+                           const char *pszPath, size_t cbPath,
+                           void *pvData, size_t cbData, uint32_t fMode)
+{
+    AssertPtrReturn(pResp, VERR_INVALID_POINTER);
+    AssertPtrReturn(pszPath, VERR_INVALID_POINTER);
+    AssertReturn(cbPath, VERR_INVALID_PARAMETER);
+
+    LogFlowFunc(("pszPath=%s, cbPath=%zu, fMode=0x%x\n",
+                 pszPath, cbPath, fMode));
+
+    int rc = pResp->writeToFile(pszPath, cbPath,
+                                pvData, cbData, fMode);
+    LogFlowFuncLeaveRC(rc);
+    return rc;
+}
+# endif /* VBOX_WITH_DRAG_AND_DROP_GH */
+
+#endif /* VBOX_WITH_DRAG_AND_DROP */
+
Index: trunk/src/VBox/Main/src-client/GuestDnDSourceImpl.cpp
===================================================================
--- trunk/src/VBox/Main/src-client/GuestDnDSourceImpl.cpp	(revision 51476)
+++ trunk/src/VBox/Main/src-client/GuestDnDSourceImpl.cpp	(revision 51476)
@@ -0,0 +1,300 @@
+/* $Id$ */
+/** @file
+ * VBox Console COM Class implementation - Guest drag'n drop source.
+ */
+
+/*
+ * Copyright (C) 2014 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include "GuestImpl.h"
+#include "GuestDnDSourceImpl.h"
+#include "GuestDnDPrivate.h"
+
+#include "Global.h"
+#include "AutoCaller.h"
+
+#include <iprt/cpp/utils.h> /* For unconst(). */
+
+#include <VBox/com/array.h>
+#include <VBox/GuestHost/DragAndDrop.h>
+#include <VBox/HostServices/DragAndDropSvc.h>
+
+#ifdef LOG_GROUP
+ #undef LOG_GROUP
+#endif
+#define LOG_GROUP LOG_GROUP_GUEST_DND
+#include <VBox/log.h>
+
+
+// constructor / destructor
+/////////////////////////////////////////////////////////////////////////////
+
+DEFINE_EMPTY_CTOR_DTOR(GuestDnDSource)
+
+HRESULT GuestDnDSource::FinalConstruct(void)
+{
+    LogFlowThisFunc(("\n"));
+    return BaseFinalConstruct();
+}
+
+void GuestDnDSource::FinalRelease(void)
+{
+    LogFlowThisFuncEnter();
+    uninit();
+    BaseFinalRelease();
+    LogFlowThisFuncLeave();
+}
+
+// public initializer/uninitializer for internal purposes only
+/////////////////////////////////////////////////////////////////////////////
+
+int GuestDnDSource::init(const ComObjPtr<Guest>& pGuest)
+{
+    LogFlowThisFuncEnter();
+
+    /* Enclose the state transition NotReady->InInit->Ready. */
+    AutoInitSpan autoInitSpan(this);
+    AssertReturn(autoInitSpan.isOk(), E_FAIL);
+
+    unconst(m_pGuest) = pGuest;
+
+    /* Confirm a successful initialization when it's the case. */
+    autoInitSpan.setSucceeded();
+
+    return VINF_SUCCESS;
+}
+
+/**
+ * Uninitializes the instance.
+ * Called from FinalRelease().
+ */
+void GuestDnDSource::uninit(void)
+{
+    LogFlowThisFunc(("\n"));
+
+    /* Enclose the state transition Ready->InUninit->NotReady. */
+    AutoUninitSpan autoUninitSpan(this);
+    if (autoUninitSpan.uninitDone())
+        return;
+}
+
+// implementation of wrapped private getters/setters for attributes
+/////////////////////////////////////////////////////////////////////////////
+
+HRESULT GuestDnDSource::dragIsPending(ULONG uScreenId,
+                                      std::vector<com::Utf8Str> &aFormats,
+                                      std::vector<DnDAction_T> &aAllowedActions,
+                                      DnDAction_T *aDefaultAction)
+{
+#if !defined(VBOX_WITH_DRAG_AND_DROP) || !defined(VBOX_WITH_DRAG_AND_DROP_GH)
+    ReturnComNotImplemented();
+#else /* VBOX_WITH_DRAG_AND_DROP */
+
+    AutoCaller autoCaller(this);
+    if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+    /* Default is ignoring the action. */
+    DnDAction_T defaultAction = DnDAction_Ignore;
+
+    HRESULT hr = S_OK;
+
+    VBOXHGCMSVCPARM paParms[1];
+    int i = 0;
+    paParms[i++].setUInt32(uScreenId);
+
+    int rc = GuestDnDInst()->hostCall(DragAndDropSvc::HOST_DND_GH_REQ_PENDING,
+                                      i, paParms);
+    if (RT_SUCCESS(rc))
+    {
+        bool fFetchResult = true;
+        GuestDnDResponse *pResp = GuestDnDInst()->response();
+        if (pResp)
+        {
+            if (pResp->waitForGuestResponse() == VERR_TIMEOUT)
+                fFetchResult = false;
+
+            if (isDnDIgnoreAction(pResp->defAction()))
+                fFetchResult = false;
+
+            /* Fetch the default action to use. */
+            if (fFetchResult)
+            {
+                defaultAction = GuestDnD::toMainAction(pResp->defAction());
+
+                GuestDnD::toFormatVector(GuestDnDInst()->supportedFormats(),
+                                         pResp->format(), aFormats);
+                GuestDnD::toMainActions(pResp->allActions(), aAllowedActions);
+            }
+        }
+
+        if (aDefaultAction)
+            *aDefaultAction = defaultAction;
+    }
+
+    if (RT_FAILURE(rc))
+        hr = setError(VBOX_E_IPRT_ERROR,
+                      tr("Unable to retrieve pending status (%Rrc)\n"), rc);
+
+    LogFlowFunc(("hr=%Rhrc, defaultAction=0x%x\n", hr, defaultAction));
+    return hr;
+#endif /* VBOX_WITH_DRAG_AND_DROP */
+}
+
+HRESULT GuestDnDSource::drop(const com::Utf8Str &aFormat,
+                             DnDAction_T aAction, ComPtr<IProgress> &aProgress)
+{
+#if !defined(VBOX_WITH_DRAG_AND_DROP) || !defined(VBOX_WITH_DRAG_AND_DROP_GH)
+    ReturnComNotImplemented();
+#else /* VBOX_WITH_DRAG_AND_DROP */
+
+    /* Input validation. */
+    if (RT_UNLIKELY((aFormat.c_str()) == NULL || *(aFormat.c_str()) == '\0'))
+        return setError(E_INVALIDARG, tr("No drop format specified"));
+
+    AutoCaller autoCaller(this);
+    if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+    uint32_t uAction = GuestDnD::toHGCMAction(aAction);
+    /* If there is no usable action, ignore this request. */
+    if (isDnDIgnoreAction(uAction))
+        return S_OK;
+
+    HRESULT hr = S_OK;
+
+    const char *pcszFormat = aFormat.c_str();
+    bool fNeedsDropDir = DnDMIMENeedsDropDir(pcszFormat, strlen(pcszFormat));
+    LogFlowFunc(("strFormat=%s, uAction=0x%x, fNeedsDropDir=%RTbool\n",
+                 pcszFormat, uAction, fNeedsDropDir));
+
+    GuestDnDResponse *pResp = GuestDnDInst()->response();
+    if (pResp)
+    {
+        /* Reset any old data. */
+        pResp->reset();
+        pResp->resetProgress(m_pGuest);
+
+        /* Set the format we are going to retrieve to have it around
+         * when retrieving the data later. */
+        pResp->setFormat(aFormat);
+
+        if (fNeedsDropDir)
+        {
+            char szDropDir[RTPATH_MAX];
+            int rc = DnDDirCreateDroppedFiles(szDropDir, sizeof(szDropDir));
+            LogFlowFunc(("rc=%Rrc, szDropDir=%s\n", rc, szDropDir));
+            if (RT_FAILURE(rc))
+                return setError(VBOX_E_IPRT_ERROR,
+                                tr("Unable to create the temporary drag'n drop directory \"%s\" (%Rrc)\n"),
+                                szDropDir, rc);
+
+            pResp->setDropDir(szDropDir);
+        }
+
+        VBOXHGCMSVCPARM paParms[4];
+        int i = 0;
+        paParms[i++].setPointer((void*)aFormat.c_str(), (uint32_t)aFormat.length() + 1);
+        paParms[i++].setUInt32((uint32_t)aFormat.length() + 1);
+        paParms[i++].setUInt32(uAction);
+
+        int rc = GuestDnDInst()->hostCall(DragAndDropSvc::HOST_DND_GH_EVT_DROPPED,
+                                          i, paParms);
+        if (RT_SUCCESS(rc))
+        {
+            /* Query the progress object to the caller. */
+            pResp->queryProgressTo(aProgress.asOutParam());
+        }
+        else
+            hr = setError(VBOX_E_IPRT_ERROR,
+                          tr("Error signalling to drop data (%Rrc)\n"), rc);
+    }
+
+    LogFlowFunc(("Returning hr=%Rhrc\n", hr));
+    return hr;
+#endif /* VBOX_WITH_DRAG_AND_DROP */
+}
+
+HRESULT GuestDnDSource::receiveData(std::vector<BYTE> &aData)
+{
+#if !defined(VBOX_WITH_DRAG_AND_DROP) || !defined(VBOX_WITH_DRAG_AND_DROP_GH)
+    ReturnComNotImplemented();
+#else /* VBOX_WITH_DRAG_AND_DROP */
+
+    /* Input validation. */
+
+    AutoCaller autoCaller(this);
+    if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+    HRESULT hr = S_OK;
+
+    GuestDnDResponse *pResp = GuestDnDInst()->response();
+    if (pResp)
+    {
+        size_t cbData = pResp->size();
+        if (cbData)
+        {
+            const void *pvData = pResp->data();
+            AssertPtr(pvData);
+
+            Utf8Str strFormat = pResp->format();
+            LogFlowFunc(("strFormat=%s, cbData=%zu, pvData=0x%p\n",
+                         strFormat.c_str(), cbData, pvData));
+
+            try
+            {
+                if (DnDMIMEHasFileURLs(strFormat.c_str(), strFormat.length()))
+                {
+                    LogFlowFunc(("strDropDir=%s\n", pResp->dropDir().c_str()));
+
+                    DnDURIList lstURI;
+                    int rc2 = lstURI.RootFromURIData(pvData, cbData, 0 /* fFlags */);
+                    if (RT_SUCCESS(rc2))
+                    {
+                        Utf8Str strURIs = lstURI.RootToString(pResp->dropDir());
+                        size_t cbURIs = strURIs.length();
+
+                        LogFlowFunc(("Found %zu root URIs (%zu bytes)\n",
+                                     lstURI.RootCount(), cbURIs));
+
+                        aData.resize(cbURIs + 1 /* Include termination */);
+                        memcpy(aData.data(), strURIs.c_str(), cbURIs);
+                    }
+                    else
+                        hr = VBOX_E_IPRT_ERROR;
+                }
+                else
+                {
+                    /* Copy the data into a safe array of bytes. */
+                    aData.resize(cbData);
+                    memcpy(aData.data(), pvData, cbData);
+                }
+            }
+            catch (std::bad_alloc &)
+            {
+                hr = E_OUTOFMEMORY;
+            }
+        }
+
+        /* Delete the data. */
+        pResp->reset();
+    }
+    else
+        hr = VBOX_E_INVALID_OBJECT_STATE;
+
+    LogFlowFunc(("Returning hr=%Rhrc\n", hr));
+    return hr;
+#endif /* VBOX_WITH_DRAG_AND_DROP */
+}
+
Index: trunk/src/VBox/Main/src-client/GuestDnDTargetImpl.cpp
===================================================================
--- trunk/src/VBox/Main/src-client/GuestDnDTargetImpl.cpp	(revision 51476)
+++ trunk/src/VBox/Main/src-client/GuestDnDTargetImpl.cpp	(revision 51476)
@@ -0,0 +1,381 @@
+/* $Id$ */
+/** @file
+ * VBox Console COM Class implementation - Guest drag'n drop target.
+ */
+
+/*
+ * Copyright (C) 2014 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include "GuestImpl.h"
+#include "GuestDnDTargetImpl.h"
+
+#include "Global.h"
+#include "AutoCaller.h"
+
+#include <iprt/cpp/utils.h> /* For unconst(). */
+
+#include <VBox/com/array.h>
+#include <VBox/HostServices/DragAndDropSvc.h>
+
+#ifdef LOG_GROUP
+ #undef LOG_GROUP
+#endif
+#define LOG_GROUP LOG_GROUP_GUEST_DND
+#include <VBox/log.h>
+
+
+// constructor / destructor
+/////////////////////////////////////////////////////////////////////////////
+
+DEFINE_EMPTY_CTOR_DTOR(GuestDnDTarget)
+
+HRESULT GuestDnDTarget::FinalConstruct(void)
+{
+    LogFlowThisFunc(("\n"));
+    return BaseFinalConstruct();
+}
+
+void GuestDnDTarget::FinalRelease(void)
+{
+    LogFlowThisFuncEnter();
+    uninit();
+    BaseFinalRelease();
+    LogFlowThisFuncLeave();
+}
+
+// public initializer/uninitializer for internal purposes only
+/////////////////////////////////////////////////////////////////////////////
+
+int GuestDnDTarget::init(const ComObjPtr<Guest>& pGuest)
+{
+    LogFlowThisFuncEnter();
+
+    /* Enclose the state transition NotReady->InInit->Ready. */
+    AutoInitSpan autoInitSpan(this);
+    AssertReturn(autoInitSpan.isOk(), E_FAIL);
+
+    unconst(m_pGuest) = pGuest;
+
+    /* Confirm a successful initialization when it's the case. */
+    autoInitSpan.setSucceeded();
+
+    return VINF_SUCCESS;
+}
+
+/**
+ * Uninitializes the instance.
+ * Called from FinalRelease().
+ */
+void GuestDnDTarget::uninit(void)
+{
+    LogFlowThisFunc(("\n"));
+
+    /* Enclose the state transition Ready->InUninit->NotReady. */
+    AutoUninitSpan autoUninitSpan(this);
+    if (autoUninitSpan.uninitDone())
+        return;
+}
+
+// implementation of wrapped private getters/setters for attributes
+/////////////////////////////////////////////////////////////////////////////
+
+HRESULT GuestDnDTarget::enter(ULONG aScreenId, ULONG aX, ULONG aY,
+                              DnDAction_T aDefaultAction,
+                              const std::vector<DnDAction_T> &aAllowedActions,
+                              const std::vector<com::Utf8Str> &aFormats,
+                              DnDAction_T *aResultAction)
+{
+#if !defined(VBOX_WITH_DRAG_AND_DROP) || !defined(VBOX_WITH_DRAG_AND_DROP_GH)
+    ReturnComNotImplemented();
+#else /* VBOX_WITH_DRAG_AND_DROP */
+
+    /* Input validation. */
+    if (aDefaultAction == DnDAction_Ignore)
+        return setError(E_INVALIDARG, tr("No default action specified"));
+    if (!aAllowedActions.size())
+        return setError(E_INVALIDARG, tr("Number of allowed actions is empty"));
+    if (!aFormats.size())
+        return setError(E_INVALIDARG, tr("Number of supported formats is empty"));
+
+    AutoCaller autoCaller(this);
+    if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+    /* Default action is ignoring. */
+    DnDAction_T resAction = DnDAction_Ignore;
+
+    /* Check & convert the drag & drop actions */
+    uint32_t uDefAction      = 0;
+    uint32_t uAllowedActions = 0;
+    GuestDnD::toHGCMActions(aDefaultAction, &uDefAction,
+                            aAllowedActions, &uAllowedActions);
+    /* If there is no usable action, ignore this request. */
+    if (isDnDIgnoreAction(uDefAction))
+        return S_OK;
+
+    /* Make a flat data string out of the supported format list. */
+    Utf8Str strFormats = GuestDnD::toFormatString(GuestDnDInst()->supportedFormats(),
+                                                  aFormats);
+    /* If there is no valid supported format, ignore this request. */
+    if (strFormats.isEmpty())
+        return S_OK;
+
+    HRESULT hr = S_OK;
+
+    /* Adjust the coordinates in a multi-monitor setup. */
+    int rc = GuestDnDInst()->adjustScreenCoordinates(aScreenId, &aX, &aY);
+    if (RT_SUCCESS(rc))
+    {
+        VBOXHGCMSVCPARM paParms[8];
+        int i = 0;
+        paParms[i++].setUInt32(aScreenId);
+        paParms[i++].setUInt32(aX);
+        paParms[i++].setUInt32(aY);
+        paParms[i++].setUInt32(uDefAction);
+        paParms[i++].setUInt32(uAllowedActions);
+        paParms[i++].setPointer((void*)strFormats.c_str(), strFormats.length() + 1);
+        paParms[i++].setUInt32(strFormats.length() + 1);
+
+        rc = GuestDnDInst()->hostCall(DragAndDropSvc::HOST_DND_HG_EVT_ENTER,
+                                      i, paParms);
+        if (RT_SUCCESS(rc))
+        {
+            GuestDnDResponse *pResp = GuestDnDInst()->response();
+            if (pResp && RT_SUCCESS(pResp->waitForGuestResponse()))
+                resAction = GuestDnD::toMainAction(pResp->defAction());
+        }
+    }
+
+    if (aResultAction)
+        *aResultAction = resAction;
+
+    LogFlowFunc(("hr=%Rhrc, resAction=%ld\n", hr, resAction));
+    return hr;
+#endif /* VBOX_WITH_DRAG_AND_DROP */
+}
+
+HRESULT GuestDnDTarget::move(ULONG aScreenId, ULONG aX, ULONG aY,
+                             DnDAction_T aDefaultAction,
+                             const std::vector<DnDAction_T> &aAllowedActions,
+                             const std::vector<com::Utf8Str> &aFormats,
+                             DnDAction_T *aResultAction)
+{
+#if !defined(VBOX_WITH_DRAG_AND_DROP) || !defined(VBOX_WITH_DRAG_AND_DROP_GH)
+    ReturnComNotImplemented();
+#else /* VBOX_WITH_DRAG_AND_DROP */
+
+    /* Input validation. */
+
+    AutoCaller autoCaller(this);
+    if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+    /* Default action is ignoring. */
+    DnDAction_T resAction = DnDAction_Ignore;
+
+    /* Check & convert the drag & drop actions. */
+    uint32_t uDefAction      = 0;
+    uint32_t uAllowedActions = 0;
+    GuestDnD::toHGCMActions(aDefaultAction, &uDefAction,
+                            aAllowedActions, &uAllowedActions);
+    /* If there is no usable action, ignore this request. */
+    if (isDnDIgnoreAction(uDefAction))
+        return S_OK;
+
+    /* Make a flat data string out of the supported format list. */
+    RTCString strFormats = GuestDnD::toFormatString(GuestDnDInst()->supportedFormats(),
+                                                    aFormats);
+    /* If there is no valid supported format, ignore this request. */
+    if (strFormats.isEmpty())
+        return S_OK;
+
+    HRESULT hr = S_OK;
+
+    int rc = GuestDnDInst()->adjustScreenCoordinates(aScreenId, &aX, &aY);
+    if (RT_SUCCESS(rc))
+    {
+        VBOXHGCMSVCPARM paParms[8];
+        int i = 0;
+        paParms[i++].setUInt32(aScreenId);
+        paParms[i++].setUInt32(aX);
+        paParms[i++].setUInt32(aY);
+        paParms[i++].setUInt32(uDefAction);
+        paParms[i++].setUInt32(uAllowedActions);
+        paParms[i++].setPointer((void*)strFormats.c_str(), strFormats.length() + 1);
+        paParms[i++].setUInt32(strFormats.length() + 1);
+
+        rc = GuestDnDInst()->hostCall(DragAndDropSvc::HOST_DND_HG_EVT_MOVE,
+                                      i, paParms);
+        if (RT_SUCCESS(rc))
+        {
+            GuestDnDResponse *pResp = GuestDnDInst()->response();
+            if (pResp && RT_SUCCESS(pResp->waitForGuestResponse()))
+                resAction = GuestDnD::toMainAction(pResp->defAction());
+        }
+    }
+
+    if (aResultAction)
+        *aResultAction = resAction;
+
+    LogFlowFunc(("hr=%Rhrc, *pResultAction=%ld\n", hr, resAction));
+    return hr;
+#endif /* VBOX_WITH_DRAG_AND_DROP */
+}
+
+HRESULT GuestDnDTarget::leave(ULONG uScreenId)
+{
+#if !defined(VBOX_WITH_DRAG_AND_DROP) || !defined(VBOX_WITH_DRAG_AND_DROP_GH)
+    ReturnComNotImplemented();
+#else /* VBOX_WITH_DRAG_AND_DROP */
+
+    AutoCaller autoCaller(this);
+    if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+    HRESULT hr = S_OK;
+    int rc = GuestDnDInst()->hostCall(DragAndDropSvc::HOST_DND_HG_EVT_LEAVE,
+                                      0 /* cParms */, NULL /* paParms */);
+    if (RT_SUCCESS(rc))
+    {
+        GuestDnDResponse *pResp = GuestDnDInst()->response();
+        if (pResp)
+            pResp->waitForGuestResponse();
+    }
+
+    LogFlowFunc(("hr=%Rhrc\n", hr));
+    return hr;
+#endif /* VBOX_WITH_DRAG_AND_DROP */
+}
+
+HRESULT GuestDnDTarget::drop(ULONG aScreenId, ULONG aX, ULONG aY,
+                             DnDAction_T aDefaultAction,
+                             const std::vector<DnDAction_T> &aAllowedActions,
+                             const std::vector<com::Utf8Str> &aFormats,
+                             com::Utf8Str &aFormat, DnDAction_T *aResultAction)
+{
+#if !defined(VBOX_WITH_DRAG_AND_DROP) || !defined(VBOX_WITH_DRAG_AND_DROP_GH)
+    ReturnComNotImplemented();
+#else /* VBOX_WITH_DRAG_AND_DROP */
+
+    /* Input validation. */
+
+    /* Everything else is optional. */
+
+    AutoCaller autoCaller(this);
+    if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+    /* Default action is ignoring. */
+    DnDAction_T resAction = DnDAction_Ignore;
+
+    /* Check & convert the drag & drop actions. */
+    uint32_t uDefAction      = 0;
+    uint32_t uAllowedActions = 0;
+    GuestDnD::toHGCMActions(aDefaultAction, &uDefAction,
+                            aAllowedActions, &uAllowedActions);
+    /* If there is no usable action, ignore this request. */
+    if (isDnDIgnoreAction(uDefAction))
+        return S_OK;
+
+    /* Make a flat data string out of the supported format list. */
+    Utf8Str strFormats = GuestDnD::toFormatString(GuestDnDInst()->supportedFormats(),
+                                                  aFormats);
+    /* If there is no valid supported format, ignore this request. */
+    if (strFormats.isEmpty())
+        return S_OK;
+
+    HRESULT hr = S_OK;
+
+    /* Adjust the coordinates in a multi-monitor setup. */
+    int rc = GuestDnDInst()->adjustScreenCoordinates(aScreenId, &aX, &aY);
+    if (RT_SUCCESS(rc))
+    {
+        VBOXHGCMSVCPARM paParms[8];
+        int i = 0;
+        paParms[i++].setUInt32(aScreenId);
+        paParms[i++].setUInt32(aX);
+        paParms[i++].setUInt32(aY);
+        paParms[i++].setUInt32(uDefAction);
+        paParms[i++].setUInt32(uAllowedActions);
+        paParms[i++].setPointer((void*)strFormats.c_str(), strFormats.length() + 1);
+        paParms[i++].setUInt32(strFormats.length() + 1);
+
+        rc = GuestDnDInst()->hostCall(DragAndDropSvc::HOST_DND_HG_EVT_DROPPED,
+                                      i, paParms);
+        if (RT_SUCCESS(rc))
+        {
+            GuestDnDResponse *pResp = GuestDnDInst()->response();
+            if (pResp && RT_SUCCESS(pResp->waitForGuestResponse()))
+            {
+                resAction = GuestDnD::toMainAction(pResp->defAction());
+                aFormat = pResp->format();
+
+                LogFlowFunc(("resFormat=%s, resAction=%RU32\n",
+                             pResp->format().c_str(), pResp->defAction()));
+            }
+        }
+    }
+
+    if (aResultAction)
+        *aResultAction = resAction;
+
+    return hr;
+#endif /* VBOX_WITH_DRAG_AND_DROP */
+}
+
+STDMETHODIMP GuestDnDTarget::sendData(ULONG aScreenId,
+                                      const com::Utf8Str &aFormat,
+                                      const std::vector<BYTE> &aData,
+                                      ComPtr<IProgress> &aProgress)
+{
+#if !defined(VBOX_WITH_DRAG_AND_DROP) || !defined(VBOX_WITH_DRAG_AND_DROP_GH)
+    ReturnComNotImplemented();
+#else /* VBOX_WITH_DRAG_AND_DROP */
+
+    /* Input validation */
+
+
+    AutoCaller autoCaller(this);
+    if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+    HRESULT hr = S_OK;
+
+    VBOXHGCMSVCPARM paParms[8];
+    int i = 0;
+    paParms[i++].setUInt32(aScreenId);
+    paParms[i++].setPointer((void*)aFormat.c_str(), (uint32_t)aFormat.length() + 1);
+    paParms[i++].setUInt32((uint32_t)aFormat.length() + 1);
+    paParms[i++].setPointer((void*)aData.data(), (uint32_t)aData.size());
+    paParms[i++].setUInt32((uint32_t)aData.size());
+
+    GuestDnDResponse *pResp = GuestDnDInst()->response();
+    if (pResp)
+    {
+        /* Reset any old progress status. */
+        pResp->resetProgress(m_pGuest);
+
+        /* Note: The actual data transfer of files/directoies is performed by the
+         *       DnD host service. */
+        int rc = GuestDnDInst()->hostCall(DragAndDropSvc::HOST_DND_HG_SND_DATA,
+                                          i, paParms);
+        if (RT_SUCCESS(rc))
+        {
+            /* Query the progress object to the caller. */
+            if (aProgress)
+                pResp->queryProgressTo(aProgress.asOutParam());
+        }
+    }
+
+    return hr;
+#endif /* VBOX_WITH_DRAG_AND_DROP */
+}
+
Index: trunk/src/VBox/Main/src-client/GuestImpl.cpp
===================================================================
--- trunk/src/VBox/Main/src-client/GuestImpl.cpp	(revision 51474)
+++ trunk/src/VBox/Main/src-client/GuestImpl.cpp	(revision 51476)
@@ -1,5 +1,5 @@
 /* $Id$ */
 /** @file
- * VirtualBox COM class implementation: Guest
+ * VirtualBox COM class implementation: Guest features.
  */
 
@@ -23,5 +23,5 @@
 #include "ProgressImpl.h"
 #ifdef VBOX_WITH_DRAG_AND_DROP
-# include "GuestDnDImpl.h"
+# include "GuestDnDPrivate.h"
 #endif
 #include "VMMDev.h"
@@ -117,16 +117,27 @@
 #endif
 
+#ifdef VBOX_WITH_DRAG_AND_DROP
     try
     {
-#ifdef VBOX_WITH_DRAG_AND_DROP
-        m_pGuestDnD = new GuestDnD(this);
-        AssertPtr(m_pGuestDnD);
+        GuestDnD::createInstance(this /* pGuest */);
+        hr = unconst(mDnDSource).createObject();
+        if (SUCCEEDED(hr))
+            hr = mDnDSource->init(this /* pGuest */);
+        if (SUCCEEDED(hr))
+        {
+            hr = unconst(mDnDTarget).createObject();
+            if (SUCCEEDED(hr))
+                hr = mDnDTarget->init(this /* pGuest */);
+        }
+
+        LogFlowFunc(("Drag'n drop initializied with hr=%Rhrc\n", hr));
+    }
+    catch (std::bad_alloc &)
+    {
+        hr = E_OUTOFMEMORY;
+    }
 #endif
-    }
-    catch(std::bad_alloc &)
-    {
-        hr = E_OUTOFMEMORY;
-    }
-
+
+    LogFlowFunc(("hr=%Rhrc\n", hr));
     return hr;
 }
@@ -157,9 +168,9 @@
     while (itSessions != mData.mGuestSessions.end())
     {
-#ifdef DEBUG
+# ifdef DEBUG
         ULONG cRefs = itSessions->second->AddRef();
         LogFlowThisFunc(("sessionID=%RU32, cRefs=%RU32\n", itSessions->first, cRefs > 1 ? cRefs - 1 : 0));
         itSessions->second->Release();
-#endif
+# endif
         itSessions->second->uninit();
         itSessions++;
@@ -169,9 +180,7 @@
 
 #ifdef VBOX_WITH_DRAG_AND_DROP
-    if (m_pGuestDnD)
-    {
-        delete m_pGuestDnD;
-        m_pGuestDnD = NULL;
-    }
+    GuestDnD::destroyInstance();
+    unconst(mDnDSource).setNull();
+    unconst(mDnDTarget).setNull();
 #endif
 
@@ -495,4 +504,44 @@
 }
 
+STDMETHODIMP Guest::COMGETTER(DnDSource)(IGuestDnDSource ** aSource)
+{
+#ifndef VBOX_WITH_DRAG_AND_DROP
+    ReturnComNotImplemented();
+#else
+    LogFlowThisFuncEnter();
+
+    CheckComArgOutPointerValid(aSource);
+
+    AutoCaller autoCaller(this);
+    if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+    /* No need to lock - lifetime constant. */
+    HRESULT hr = mDnDSource.queryInterfaceTo(aSource);
+
+    LogFlowFuncLeaveRC(hr);
+    return hr;
+#endif /* VBOX_WITH_DRAG_AND_DROP */
+}
+
+STDMETHODIMP Guest::COMGETTER(DnDTarget)(IGuestDnDTarget ** aTarget)
+{
+#ifndef VBOX_WITH_DRAG_AND_DROP
+    ReturnComNotImplemented();
+#else
+    LogFlowThisFuncEnter();
+
+    CheckComArgOutPointerValid(aTarget);
+
+    AutoCaller autoCaller(this);
+    if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+    /* No need to lock - lifetime constant. */
+    HRESULT hr = mDnDTarget.queryInterfaceTo(aTarget);
+
+    LogFlowFuncLeaveRC(hr);
+    return hr;
+#endif /* VBOX_WITH_DRAG_AND_DROP */
+}
+
 STDMETHODIMP Guest::COMGETTER(EventSource)(IEventSource ** aEventSource)
 {
@@ -507,5 +556,5 @@
     if (FAILED(autoCaller.rc())) return autoCaller.rc();
 
-    // no need to lock - lifetime constant
+    /* No need to lock - lifetime constant. */
     mEventSource.queryInterfaceTo(aEventSource);
 
@@ -821,5 +870,5 @@
     {
         /** @todo */
-        return E_NOTIMPL;    
+        return E_NOTIMPL;
     }
     else
@@ -835,5 +884,5 @@
                 if (!aAllowInteractiveLogon)
                     u32Flags = VMMDEV_SETCREDENTIALS_NOLOCALLOGON;
-    
+
                 pVMMDevPort->pfnSetCredentials(pVMMDevPort,
                                                Utf8Str(aUserName).c_str(),
@@ -848,165 +897,4 @@
     return setError(VBOX_E_VM_ERROR,
                     tr("VMM device is not available (is the VM running?)"));
-}
-
-STDMETHODIMP Guest::DragHGEnter(ULONG uScreenId, ULONG uX, ULONG uY,
-                                DragAndDropAction_T defaultAction,
-                                ComSafeArrayIn(DragAndDropAction_T, allowedActions),
-                                ComSafeArrayIn(IN_BSTR, formats),
-                                DragAndDropAction_T *pResultAction)
-{
-    /* Input validation */
-    CheckComArgSafeArrayNotNull(allowedActions);
-    CheckComArgSafeArrayNotNull(formats);
-    CheckComArgOutPointerValid(pResultAction);
-
-    AutoCaller autoCaller(this);
-    if (FAILED(autoCaller.rc())) return autoCaller.rc();
-
-#ifdef VBOX_WITH_DRAG_AND_DROP
-    return m_pGuestDnD->dragHGEnter(uScreenId, uX, uY, defaultAction,
-                                    ComSafeArrayInArg(allowedActions),
-                                    ComSafeArrayInArg(formats),
-                                    pResultAction);
-#else /* VBOX_WITH_DRAG_AND_DROP */
-    ReturnComNotImplemented();
-#endif /* !VBOX_WITH_DRAG_AND_DROP */
-}
-
-STDMETHODIMP Guest::DragHGMove(ULONG uScreenId, ULONG uX, ULONG uY,
-                               DragAndDropAction_T defaultAction,
-                               ComSafeArrayIn(DragAndDropAction_T, allowedActions),
-                               ComSafeArrayIn(IN_BSTR, formats),
-                               DragAndDropAction_T *pResultAction)
-{
-    /* Input validation */
-    CheckComArgSafeArrayNotNull(allowedActions);
-    CheckComArgSafeArrayNotNull(formats);
-    CheckComArgOutPointerValid(pResultAction);
-
-    AutoCaller autoCaller(this);
-    if (FAILED(autoCaller.rc())) return autoCaller.rc();
-
-#ifdef VBOX_WITH_DRAG_AND_DROP
-    return m_pGuestDnD->dragHGMove(uScreenId, uX, uY, defaultAction,
-                                   ComSafeArrayInArg(allowedActions),
-                                   ComSafeArrayInArg(formats),
-                                   pResultAction);
-#else /* VBOX_WITH_DRAG_AND_DROP */
-    ReturnComNotImplemented();
-#endif /* !VBOX_WITH_DRAG_AND_DROP */
-}
-
-STDMETHODIMP Guest::DragHGLeave(ULONG uScreenId)
-{
-    AutoCaller autoCaller(this);
-    if (FAILED(autoCaller.rc())) return autoCaller.rc();
-
-#ifdef VBOX_WITH_DRAG_AND_DROP
-    return m_pGuestDnD->dragHGLeave(uScreenId);
-#else /* VBOX_WITH_DRAG_AND_DROP */
-    ReturnComNotImplemented();
-#endif /* !VBOX_WITH_DRAG_AND_DROP */
-}
-
-STDMETHODIMP Guest::DragHGDrop(ULONG uScreenId, ULONG uX, ULONG uY,
-                               DragAndDropAction_T defaultAction,
-                               ComSafeArrayIn(DragAndDropAction_T, allowedActions),
-                               ComSafeArrayIn(IN_BSTR, formats),
-                               BSTR *pstrFormat, DragAndDropAction_T *pResultAction)
-{
-    /* Input validation */
-    CheckComArgSafeArrayNotNull(allowedActions);
-    CheckComArgSafeArrayNotNull(formats);
-    CheckComArgOutPointerValid(pstrFormat);
-    CheckComArgOutPointerValid(pResultAction);
-
-    AutoCaller autoCaller(this);
-    if (FAILED(autoCaller.rc())) return autoCaller.rc();
-
-#ifdef VBOX_WITH_DRAG_AND_DROP
-    return m_pGuestDnD->dragHGDrop(uScreenId, uX, uY,
-                                   defaultAction,
-                                   ComSafeArrayInArg(allowedActions),
-                                   ComSafeArrayInArg(formats),
-                                   pstrFormat, pResultAction);
-#else /* VBOX_WITH_DRAG_AND_DROP */
-    ReturnComNotImplemented();
-#endif /* !VBOX_WITH_DRAG_AND_DROP */
-}
-
-STDMETHODIMP Guest::DragHGPutData(ULONG uScreenId, IN_BSTR bstrFormat,
-                                  ComSafeArrayIn(BYTE, data),
-                                  IProgress **ppProgress)
-{
-    /* Input validation */
-    CheckComArgStrNotEmptyOrNull(bstrFormat);
-    CheckComArgSafeArrayNotNull(data);
-    CheckComArgOutPointerValid(ppProgress);
-
-    AutoCaller autoCaller(this);
-    if (FAILED(autoCaller.rc())) return autoCaller.rc();
-
-#ifdef VBOX_WITH_DRAG_AND_DROP
-    return m_pGuestDnD->dragHGPutData(uScreenId, bstrFormat,
-                                      ComSafeArrayInArg(data), ppProgress);
-#else /* VBOX_WITH_DRAG_AND_DROP */
-    ReturnComNotImplemented();
-#endif /* !VBOX_WITH_DRAG_AND_DROP */
-}
-
-STDMETHODIMP Guest::DragGHPending(ULONG uScreenId,
-                                  ComSafeArrayOut(BSTR, formats),
-                                  ComSafeArrayOut(DragAndDropAction_T, allowedActions),
-                                  DragAndDropAction_T *pDefaultAction)
-{
-    /* Input validation */
-    CheckComArgSafeArrayNotNull(formats);
-    CheckComArgSafeArrayNotNull(allowedActions);
-    CheckComArgOutPointerValid(pDefaultAction);
-
-    AutoCaller autoCaller(this);
-    if (FAILED(autoCaller.rc())) return autoCaller.rc();
-
-#if defined(VBOX_WITH_DRAG_AND_DROP) && defined(VBOX_WITH_DRAG_AND_DROP_GH)
-    return m_pGuestDnD->dragGHPending(uScreenId,
-                                      ComSafeArrayOutArg(formats),
-                                      ComSafeArrayOutArg(allowedActions),
-                                      pDefaultAction);
-#else /* VBOX_WITH_DRAG_AND_DROP */
-    ReturnComNotImplemented();
-#endif /* !VBOX_WITH_DRAG_AND_DROP */
-}
-
-STDMETHODIMP Guest::DragGHDropped(IN_BSTR bstrFormat, DragAndDropAction_T action,
-                                  IProgress **ppProgress)
-{
-    /* Input validation */
-    CheckComArgStrNotEmptyOrNull(bstrFormat);
-    CheckComArgOutPointerValid(ppProgress);
-
-    AutoCaller autoCaller(this);
-    if (FAILED(autoCaller.rc())) return autoCaller.rc();
-
-#if defined(VBOX_WITH_DRAG_AND_DROP) && defined(VBOX_WITH_DRAG_AND_DROP_GH)
-    return m_pGuestDnD->dragGHDropped(bstrFormat, action, ppProgress);
-#else /* VBOX_WITH_DRAG_AND_DROP */
-    ReturnComNotImplemented();
-#endif /* !VBOX_WITH_DRAG_AND_DROP */
-}
-
-STDMETHODIMP Guest::DragGHGetData(ComSafeArrayOut(BYTE, data))
-{
-    /* Input validation */
-    CheckComArgSafeArrayNotNull(data);
-
-    AutoCaller autoCaller(this);
-    if (FAILED(autoCaller.rc())) return autoCaller.rc();
-
-#if defined(VBOX_WITH_DRAG_AND_DROP) && defined(VBOX_WITH_DRAG_AND_DROP_GH)
-    return m_pGuestDnD->dragGHGetData(ComSafeArrayOutArg(data));
-#else /* VBOX_WITH_DRAG_AND_DROP */
-    ReturnComNotImplemented();
-#endif /* !VBOX_WITH_DRAG_AND_DROP */
 }
 
Index: trunk/src/VBox/Main/src-client/SessionImpl.cpp
===================================================================
--- trunk/src/VBox/Main/src-client/SessionImpl.cpp	(revision 51474)
+++ trunk/src/VBox/Main/src-client/SessionImpl.cpp	(revision 51476)
@@ -5,5 +5,5 @@
 
 /*
- * Copyright (C) 2006-2013 Oracle Corporation
+ * Copyright (C) 2006-2014 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
@@ -784,17 +784,17 @@
 }
 
-STDMETHODIMP Session::OnDragAndDropModeChange(DragAndDropMode_T aDragAndDropMode)
-{
-    LogFlowThisFunc(("\n"));
-
-    AutoCaller autoCaller(this);
-    AssertComRCReturn(autoCaller.rc(), autoCaller.rc());
-
-    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
-    AssertReturn(mState == SessionState_Locked, VBOX_E_INVALID_VM_STATE);
-#ifndef VBOX_COM_INPROC_API_CLIENT
-    AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE);
-
-    return mConsole->onDragAndDropModeChange(aDragAndDropMode);
+STDMETHODIMP Session::OnDnDModeChange(DnDMode_T aDragAndDropMode)
+{
+    LogFlowThisFunc(("\n"));
+
+    AutoCaller autoCaller(this);
+    AssertComRCReturn(autoCaller.rc(), autoCaller.rc());
+
+    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
+    AssertReturn(mState == SessionState_Locked, VBOX_E_INVALID_VM_STATE);
+#ifndef VBOX_COM_INPROC_API_CLIENT
+    AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE);
+
+    return mConsole->onDnDModeChange(aDragAndDropMode);
 #else
     return S_OK;
Index: trunk/src/VBox/Main/src-server/MachineImpl.cpp
===================================================================
--- trunk/src/VBox/Main/src-server/MachineImpl.cpp	(revision 51474)
+++ trunk/src/VBox/Main/src-server/MachineImpl.cpp	(revision 51476)
@@ -199,5 +199,5 @@
 
     mClipboardMode = ClipboardMode_Disabled;
-    mDragAndDropMode = DragAndDropMode_Disabled;
+    mDnDMode = DnDMode_Disabled;
     mGuestPropertyNotificationPatterns = "";
 
@@ -3036,7 +3036,7 @@
 }
 
-STDMETHODIMP Machine::COMGETTER(DragAndDropMode)(DragAndDropMode_T *aDragAndDropMode)
-{
-    CheckComArgOutPointerValid(aDragAndDropMode);
+STDMETHODIMP Machine::COMGETTER(DnDMode)(DnDMode_T *aDnDMode)
+{
+    CheckComArgOutPointerValid(aDnDMode);
 
     AutoCaller autoCaller(this);
@@ -3045,10 +3045,10 @@
     AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
 
-    *aDragAndDropMode = mHWData->mDragAndDropMode;
-
-    return S_OK;
-}
-
-STDMETHODIMP Machine::COMSETTER(DragAndDropMode)(DragAndDropMode_T aDragAndDropMode)
+    *aDnDMode = mHWData->mDnDMode;
+
+    return S_OK;
+}
+
+STDMETHODIMP Machine::COMSETTER(DnDMode)(DnDMode_T aDnDMode)
 {
     HRESULT rc = S_OK;
@@ -3060,5 +3060,5 @@
 
     alock.release();
-    rc = onDragAndDropModeChange(aDragAndDropMode);
+    rc = onDnDModeChange(aDnDMode);
     alock.acquire();
     if (FAILED(rc)) return rc;
@@ -3066,5 +3066,5 @@
     setModified(IsModified_MachineData);
     mHWData.backup();
-    mHWData->mDragAndDropMode = aDragAndDropMode;
+    mHWData->mDnDMode = aDnDMode;
 
     /** Save settings if online - @todo why is this required? -- @bugref{6818} */
@@ -9515,5 +9515,5 @@
 
         // drag'n'drop
-        mHWData->mDragAndDropMode = data.dragAndDropMode;
+        mHWData->mDnDMode = data.dndMode;
 
         // guest settings
@@ -10808,5 +10808,5 @@
 
         // drag'n'drop
-        data.dragAndDropMode = mHWData->mDragAndDropMode;
+        data.dndMode = mHWData->mDnDMode;
 
         /* Guest */
@@ -14470,5 +14470,5 @@
  * @note Locks this object for reading.
  */
-HRESULT SessionMachine::onDragAndDropModeChange(DragAndDropMode_T aDragAndDropMode)
+HRESULT SessionMachine::onDnDModeChange(DnDMode_T aDnDMode)
 {
     LogFlowThisFunc(("\n"));
@@ -14487,5 +14487,5 @@
         return S_OK;
 
-    return directControl->OnDragAndDropModeChange(aDragAndDropMode);
+    return directControl->OnDnDModeChange(aDnDMode);
 }
 
Index: trunk/src/VBox/Main/xml/Settings.cpp
===================================================================
--- trunk/src/VBox/Main/xml/Settings.cpp	(revision 51474)
+++ trunk/src/VBox/Main/xml/Settings.cpp	(revision 51476)
@@ -1930,5 +1930,5 @@
           fEmulatedUSBCardReader(false),
           clipboardMode(ClipboardMode_Disabled),
-          dragAndDropMode(DragAndDropMode_Disabled),
+          dndMode(DnDMode_Disabled),
           ulMemoryBalloonSize(0),
           fPageFusionEnabled(false)
@@ -2013,5 +2013,5 @@
                   && (llSharedFolders           == h.llSharedFolders)
                   && (clipboardMode             == h.clipboardMode)
-                  && (dragAndDropMode           == h.dragAndDropMode)
+                  && (dndMode           == h.dndMode)
                   && (ulMemoryBalloonSize       == h.ulMemoryBalloonSize)
                   && (fPageFusionEnabled        == h.fPageFusionEnabled)
@@ -3208,11 +3208,11 @@
             {
                 if (strTemp == "Disabled")
-                    hw.dragAndDropMode = DragAndDropMode_Disabled;
+                    hw.dndMode = DnDMode_Disabled;
                 else if (strTemp == "HostToGuest")
-                    hw.dragAndDropMode = DragAndDropMode_HostToGuest;
+                    hw.dndMode = DnDMode_HostToGuest;
                 else if (strTemp == "GuestToHost")
-                    hw.dragAndDropMode = DragAndDropMode_GuestToHost;
+                    hw.dndMode = DnDMode_GuestToHost;
                 else if (strTemp == "Bidirectional")
-                    hw.dragAndDropMode = DragAndDropMode_Bidirectional;
+                    hw.dndMode = DnDMode_Bidirectional;
                 else
                     throw ConfigFileError(this, pelmHwChild, N_("Invalid value '%s' in DragAndDrop/@mode attribute"), strTemp.c_str());
@@ -4682,10 +4682,10 @@
     xml::ElementNode *pelmDragAndDrop = pelmHardware->createChild("DragAndDrop");
     const char *pcszDragAndDrop;
-    switch (hw.dragAndDropMode)
-    {
-        default: /*case DragAndDropMode_Disabled:*/ pcszDragAndDrop = "Disabled"; break;
-        case DragAndDropMode_HostToGuest: pcszDragAndDrop = "HostToGuest"; break;
-        case DragAndDropMode_GuestToHost: pcszDragAndDrop = "GuestToHost"; break;
-        case DragAndDropMode_Bidirectional: pcszDragAndDrop = "Bidirectional"; break;
+    switch (hw.dndMode)
+    {
+        default: /*case DnDMode_Disabled:*/ pcszDragAndDrop = "Disabled"; break;
+        case DnDMode_HostToGuest: pcszDragAndDrop = "HostToGuest"; break;
+        case DnDMode_GuestToHost: pcszDragAndDrop = "GuestToHost"; break;
+        case DnDMode_Bidirectional: pcszDragAndDrop = "Bidirectional"; break;
     }
     pelmDragAndDrop->setAttribute("mode", pcszDragAndDrop);
