Index: trunk/src/VBox/Main/src-client/GuestDnDSourceImpl.cpp
===================================================================
--- trunk/src/VBox/Main/src-client/GuestDnDSourceImpl.cpp	(revision 55514)
+++ trunk/src/VBox/Main/src-client/GuestDnDSourceImpl.cpp	(revision 55520)
@@ -78,12 +78,5 @@
         , mpCtx(pCtx) { }
 
-    virtual ~RecvDataTask(void)
-    {
-        if (mpCtx)
-        {
-            delete mpCtx;
-            mpCtx = NULL;
-        }
-    }
+    virtual ~RecvDataTask(void) { }
 
     PRECVDATACTX getCtx(void) { return mpCtx; }
@@ -106,5 +99,6 @@
     /* Note: Never ever rely on information from the guest; the host dictates what and
      *       how to do something, so try to negogiate a sensible value here later. */
-    m_cbBlockSize = _64K; /** @todo Make this configurable. */
+    mData.mcbBlockSize    = _64K; /** @todo Make this configurable. */
+    mData.mfDropIsPending = false;
 
     LogFlowThisFunc(("\n"));
@@ -247,5 +241,5 @@
 
     /* Determine guest DnD protocol to use. */
-    GuestDnDBase::getProtocolVersion(&mData.mProtocolVersion);
+    GuestDnDBase::getProtocolVersion(&mDataBase.mProtocolVersion);
 
     /* Default is ignoring the action. */
@@ -254,9 +248,9 @@
     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);
+    GuestDnDMsg Msg;
+    Msg.setType(DragAndDropSvc::HOST_DND_GH_REQ_PENDING);
+    Msg.setNextUInt32(uScreenId);
+
+    int rc = GuestDnDInst()->hostCall(Msg.getType(), Msg.getCount(), Msg.getParms());
     if (RT_SUCCESS(rc))
     {
@@ -313,4 +307,9 @@
         return S_OK;
 
+    if (ASMAtomicReadBool(&mData.mfDropIsPending))
+        return setError(E_INVALIDARG, tr("Another drop operation already is in progress"));
+
+    ASMAtomicWriteBool(&mData.mfDropIsPending, true);
+
     HRESULT hr = S_OK;
 
@@ -325,12 +324,9 @@
         try
         {
-            PRECVDATACTX pRecvCtx = new RECVDATACTX;
-            RT_BZERO(pRecvCtx, sizeof(RECVDATACTX));
-
-            pRecvCtx->mpSource = this;
-            pRecvCtx->mpResp   = pResp;
-            pRecvCtx->mFormat  = aFormat;
-
-            RecvDataTask *pTask = new RecvDataTask(this, pRecvCtx);
+            mData.mRecvCtx.mpSource = this;
+            mData.mRecvCtx.mpResp   = pResp;
+            mData.mRecvCtx.mFormat  = aFormat;
+
+            RecvDataTask *pTask = new RecvDataTask(this, &mData.mRecvCtx);
             AssertReturn(pTask->isOk(), pTask->getRC());
 
@@ -344,6 +340,4 @@
                 /* Note: pTask is now owned by the worker thread. */
             }
-            else if (pRecvCtx)
-                delete pRecvCtx;
         }
         catch(std::bad_alloc &)
@@ -355,4 +349,6 @@
     }
     /** @todo SetError(...) */
+
+    ASMAtomicWriteBool(&mData.mfDropIsPending, false);
 
     LogFlowFunc(("Returning hr=%Rhrc\n", hr));
@@ -372,61 +368,46 @@
     if (FAILED(autoCaller.rc())) return autoCaller.rc();
 
+    if (ASMAtomicReadBool(&mData.mfDropIsPending))
+        return setError(E_INVALIDARG, tr("Current drop operation still running"));
+
+    PRECVDATACTX pCtx = &mData.mRecvCtx;
+
+    if (pCtx->mData.vecData.empty())
+    {
+        aData.resize(0);
+        return S_OK;
+    }
+
     HRESULT hr = S_OK;
-
-#if 0
-    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.front(), 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.front(), pvData, cbData);
-                }
-            }
-            catch (std::bad_alloc &)
-            {
-                hr = E_OUTOFMEMORY;
-            }
-        }
-
-        /* Delete the data. */
-        pResp->reset();
-    }
-    else
-        hr = VBOX_E_INVALID_OBJECT_STATE;
-#endif
-
-    LogFlowFunc(("Returning hr=%Rhrc\n", hr));
+    size_t cbData;
+
+    try
+    {
+        bool fHasURIList = DnDMIMENeedsDropDir(pCtx->mFormat.c_str(), pCtx->mFormat.length());
+        if (fHasURIList)
+        {
+            Utf8Str strURIs = pCtx->mURI.lstURI.RootToString(pCtx->mURI.strDropDir);
+            cbData = strURIs.length();
+
+            LogFlowFunc(("Found %zu root URIs (%zu bytes)\n", pCtx->mURI.lstURI.RootCount(), cbData));
+
+            aData.resize(cbData + 1 /* Include termination */);
+            memcpy(&aData.front(), strURIs.c_str(), cbData);
+        }
+        else
+        {
+            cbData = pCtx->mData.vecData.size();
+
+            /* Copy the data into a safe array of bytes. */
+            aData.resize(cbData);
+            memcpy(&aData.front(), &pCtx->mData.vecData[0], cbData);
+        }
+    }
+    catch (std::bad_alloc &)
+    {
+        hr = E_OUTOFMEMORY;
+    }
+
+    LogFlowFunc(("Returning cbData=%zu, hr=%Rhrc\n", cbData, hr));
     return hr;
 #endif /* VBOX_WITH_DRAG_AND_DROP */
@@ -451,5 +432,5 @@
     {
         if (   cbData > cbTotalSize
-            || cbData > m_cbBlockSize)
+            || cbData > mData.mcbBlockSize)
         {
             LogFlowFunc(("Data sizes invalid: cbData=%RU32, cbTotalSize=%RU64\n", cbData, cbTotalSize));
@@ -586,5 +567,5 @@
 
             /* Note: Protocol v1 does not send any file sizes, so always 0. */
-            if (mData.mProtocolVersion >= 2)
+            if (mDataBase.mProtocolVersion >= 2)
                 rc = pCtx->mURI.objURI.SetSize(cbSize);
         }
@@ -645,10 +626,10 @@
             if (pCtx->mURI.objURI.IsComplete())
             {
-                /* Prepare URI object for next use. */
-                pCtx->mURI.objURI.Reset();
-
                 /** @todo Sanitize path. */
                 LogRel2(("DnD: File transfer to host complete: %s\n", pCtx->mURI.objURI.GetDestPath().c_str()));
                 rc = VINF_EOF;
+
+                /* Prepare URI object for next use. */
+                pCtx->mURI.objURI.Reset();
             }
         }
@@ -839,5 +820,5 @@
     REGISTER_CALLBACK(DragAndDropSvc::GUEST_DND_GH_SND_DATA);
     REGISTER_CALLBACK(DragAndDropSvc::GUEST_DND_GH_SND_DIR);
-    if (mData.mProtocolVersion >= 2)
+    if (mDataBase.mProtocolVersion >= 2)
         REGISTER_CALLBACK(DragAndDropSvc::GUEST_DND_GH_SND_FILE_HDR);
     REGISTER_CALLBACK(DragAndDropSvc::GUEST_DND_GH_SND_FILE_DATA);
@@ -884,5 +865,5 @@
     UNREGISTER_CALLBACK(DragAndDropSvc::GUEST_DND_GH_SND_DATA);
     UNREGISTER_CALLBACK(DragAndDropSvc::GUEST_DND_GH_SND_DIR);
-    if (mData.mProtocolVersion >= 2)
+    if (mDataBase.mProtocolVersion >= 2)
         UNREGISTER_CALLBACK(DragAndDropSvc::GUEST_DND_GH_SND_FILE_HDR);
     UNREGISTER_CALLBACK(DragAndDropSvc::GUEST_DND_GH_SND_FILE_DATA);
@@ -1024,5 +1005,5 @@
             AssertReturn(DragAndDropSvc::CB_MAGIC_DND_GH_SND_FILE_DATA == pCBData->hdr.u32Magic, VERR_INVALID_PARAMETER);
 
-            if (pThis->mData.mProtocolVersion <= 1)
+            if (pThis->mDataBase.mProtocolVersion <= 1)
             {
                 /**
Index: trunk/src/VBox/Main/src-client/GuestDnDTargetImpl.cpp
===================================================================
--- trunk/src/VBox/Main/src-client/GuestDnDTargetImpl.cpp	(revision 55514)
+++ trunk/src/VBox/Main/src-client/GuestDnDTargetImpl.cpp	(revision 55520)
@@ -111,5 +111,5 @@
     /* Note: Never ever rely on information from the guest; the host dictates what and
      *       how to do something, so try to negogiate a sensible value here later. */
-    m_cbBlockSize = _64K; /** @todo Make this configurable. */
+    mData.mcbBlockSize = _64K; /** @todo Make this configurable. */
 
     LogFlowThisFunc(("\n"));
@@ -261,5 +261,5 @@
 
     /* Determine guest DnD protocol to use. */
-    GuestDnDBase::getProtocolVersion(&mData.mProtocolVersion);
+    GuestDnDBase::getProtocolVersion(&mDataBase.mProtocolVersion);
 
     /* Default action is ignoring. */
@@ -287,16 +287,15 @@
     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);
+        GuestDnDMsg Msg;
+        Msg.setType(DragAndDropSvc::HOST_DND_HG_EVT_ENTER);
+        Msg.setNextUInt32(aScreenId);
+        Msg.setNextUInt32(aX);
+        Msg.setNextUInt32(aY);
+        Msg.setNextUInt32(uDefAction);
+        Msg.setNextUInt32(uAllowedActions);
+        Msg.setNextPointer((void*)strFormats.c_str(), strFormats.length() + 1);
+        Msg.setNextUInt32(strFormats.length() + 1);
+
+        rc = GuestDnDInst()->hostCall(Msg.getType(), Msg.getCount(), Msg.getParms());
         if (RT_SUCCESS(rc))
         {
@@ -353,16 +352,15 @@
     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);
+        GuestDnDMsg Msg;
+        Msg.setType(DragAndDropSvc::HOST_DND_HG_EVT_MOVE);
+        Msg.setNextUInt32(aScreenId);
+        Msg.setNextUInt32(aX);
+        Msg.setNextUInt32(aY);
+        Msg.setNextUInt32(uDefAction);
+        Msg.setNextUInt32(uAllowedActions);
+        Msg.setNextPointer((void*)strFormats.c_str(), strFormats.length() + 1);
+        Msg.setNextUInt32(strFormats.length() + 1);
+
+        rc = GuestDnDInst()->hostCall(Msg.getType(), Msg.getCount(), Msg.getParms());
         if (RT_SUCCESS(rc))
         {
@@ -446,16 +444,15 @@
     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);
+        GuestDnDMsg Msg;
+        Msg.setType(DragAndDropSvc::HOST_DND_HG_EVT_DROPPED);
+        Msg.setNextUInt32(aScreenId);
+        Msg.setNextUInt32(aX);
+        Msg.setNextUInt32(aY);
+        Msg.setNextUInt32(uDefAction);
+        Msg.setNextUInt32(uAllowedActions);
+        Msg.setNextPointer((void*)strFormats.c_str(), strFormats.length() + 1);
+        Msg.setNextUInt32(strFormats.length() + 1);
+
+        rc = GuestDnDInst()->hostCall(Msg.getType(), Msg.getCount(), Msg.getParms());
         if (RT_SUCCESS(rc))
         {
@@ -669,5 +666,5 @@
         return VERR_BUFFER_OVERFLOW;
 
-    LogFlowFunc(("Sending directory \"%s\" using protocol v%RU32 ...\n", strPath.c_str(), mData.mProtocolVersion));
+    LogFlowFunc(("Sending directory \"%s\" using protocol v%RU32 ...\n", strPath.c_str(), mDataBase.mProtocolVersion));
 
     pMsg->setType(DragAndDropSvc::HOST_DND_HG_SND_DIR);
@@ -690,5 +687,5 @@
 
     LogFlowFunc(("Sending \"%s\" (%RU32 bytes buffer) using protocol v%RU32 ...\n",
-                 strPathSrc.c_str(), m_cbBlockSize, mData.mProtocolVersion));
+                 strPathSrc.c_str(), mData.mcbBlockSize, mDataBase.mProtocolVersion));
 
     bool fOpen = aFile.IsOpen();
@@ -703,5 +700,5 @@
     if (RT_SUCCESS(rc))
     {
-        if (mData.mProtocolVersion >= 2)
+        if (mDataBase.mProtocolVersion >= 2)
         {
             if (!fOpen)
@@ -772,5 +769,5 @@
     /* Protocol version 1 sends the file path *every* time with a new file chunk.
      * In protocol version 2 we only do this once with HOST_DND_HG_SND_FILE_HDR. */
-    if (mData.mProtocolVersion <= 1)
+    if (mDataBase.mProtocolVersion <= 1)
     {
         pMsg->setNextString(aFile.GetSourcePath().c_str());                  /* pvName */
@@ -790,5 +787,5 @@
         pCtx->mData.cbProcessed += cbRead;
 
-        if (mData.mProtocolVersion <= 1)
+        if (mDataBase.mProtocolVersion <= 1)
         {
             pMsg->setNextPointer(pCtx->mURI.pvScratchBuf, cbRead);  /* pvData */
@@ -944,5 +941,5 @@
     }
 
-    void *pvBuf = RTMemAlloc(m_cbBlockSize);
+    void *pvBuf = RTMemAlloc(mData.mcbBlockSize);
     if (!pvBuf)
         return VERR_NO_MEMORY;
@@ -971,5 +968,5 @@
     /* Host callbacks. */
     REGISTER_CALLBACK(DragAndDropSvc::HOST_DND_HG_SND_DIR);
-    if (mData.mProtocolVersion >= 2)
+    if (mDataBase.mProtocolVersion >= 2)
         REGISTER_CALLBACK(DragAndDropSvc::HOST_DND_HG_SND_FILE_HDR);
     REGISTER_CALLBACK(DragAndDropSvc::HOST_DND_HG_SND_FILE_DATA);
@@ -981,5 +978,5 @@
          */
         pCtx->mURI.pvScratchBuf = pvBuf;
-        pCtx->mURI.cbScratchBuf = m_cbBlockSize;
+        pCtx->mURI.cbScratchBuf = mData.mcbBlockSize;
 
         /*
@@ -1047,5 +1044,5 @@
     /* Host callbacks. */
     UNREGISTER_CALLBACK(DragAndDropSvc::HOST_DND_HG_SND_DIR);
-    if (mData.mProtocolVersion >= 2)
+    if (mDataBase.mProtocolVersion >= 2)
         UNREGISTER_CALLBACK(DragAndDropSvc::HOST_DND_HG_SND_FILE_HDR);
     UNREGISTER_CALLBACK(DragAndDropSvc::HOST_DND_HG_SND_FILE_DATA);
