Index: trunk/src/VBox/Main/include/GuestDnDSourceImpl.h
===================================================================
--- trunk/src/VBox/Main/include/GuestDnDSourceImpl.h	(revision 55535)
+++ trunk/src/VBox/Main/include/GuestDnDSourceImpl.h	(revision 55539)
@@ -84,7 +84,7 @@
 protected:
 
-    int i_receiveData(PRECVDATACTX pCtx);
-    int i_receiveRawData(PRECVDATACTX pCtx);
-    int i_receiveURIData(PRECVDATACTX pCtx);
+    int i_receiveData(PRECVDATACTX pCtx, RTMSINTERVAL msTimeout);
+    int i_receiveRawData(PRECVDATACTX pCtx, RTMSINTERVAL msTimeout);
+    int i_receiveURIData(PRECVDATACTX pCtx, RTMSINTERVAL msTimeout);
     int i_updateProcess(PRECVDATACTX pCtx, uint32_t cbDataAdd);
 
Index: trunk/src/VBox/Main/src-client/GuestDnDPrivate.cpp
===================================================================
--- trunk/src/VBox/Main/src-client/GuestDnDPrivate.cpp	(revision 55535)
+++ trunk/src/VBox/Main/src-client/GuestDnDPrivate.cpp	(revision 55539)
@@ -413,6 +413,19 @@
             AssertReturn(DragAndDropSvc::CB_MAGIC_DND_HG_REQ_DATA == pCBData->hdr.u32Magic, VERR_INVALID_PARAMETER);
 
-            setFormat(pCBData->pszFormat);
-            rc = notifyAboutGuestResponse();
+            if (   pCBData->cbFormat == 0
+                || pCBData->cbFormat >  _64K)
+            {
+                rc = VERR_INVALID_PARAMETER;
+            }
+            else
+            {
+                setFormat(pCBData->pszFormat);
+
+                rc = VINF_SUCCESS;
+            }
+
+            int rc2 = notifyAboutGuestResponse();
+            if (RT_SUCCESS(rc))
+                rc = rc2;
             break;
         }
@@ -440,9 +453,21 @@
             AssertReturn(DragAndDropSvc::CB_MAGIC_DND_GH_ACK_PENDING == pCBData->hdr.u32Magic, VERR_INVALID_PARAMETER);
 
-            setFormat    (pCBData->pszFormat);
-            setDefAction (pCBData->uDefAction);
-            setAllActions(pCBData->uAllActions);
-
-            rc = notifyAboutGuestResponse();
+            if (   pCBData->cbFormat == 0
+                || pCBData->cbFormat >  _64K)
+            {
+                rc = VERR_INVALID_PARAMETER;
+            }
+            else
+            {
+                setFormat    (pCBData->pszFormat);
+                setDefAction (pCBData->uDefAction);
+                setAllActions(pCBData->uAllActions);
+
+                rc = VINF_SUCCESS;
+            }
+
+            int rc2 = notifyAboutGuestResponse();
+            if (RT_SUCCESS(rc))
+                rc = rc2;
             break;
         }
Index: trunk/src/VBox/Main/src-client/GuestDnDSourceImpl.cpp
===================================================================
--- trunk/src/VBox/Main/src-client/GuestDnDSourceImpl.cpp	(revision 55535)
+++ trunk/src/VBox/Main/src-client/GuestDnDSourceImpl.cpp	(revision 55539)
@@ -229,8 +229,6 @@
 /////////////////////////////////////////////////////////////////////////////
 
-HRESULT GuestDnDSource::dragIsPending(ULONG uScreenId,
-                                      std::vector<com::Utf8Str> &aFormats,
-                                      std::vector<DnDAction_T> &aAllowedActions,
-                                      DnDAction_T *aDefaultAction)
+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)
@@ -282,5 +280,5 @@
     if (RT_FAILURE(rc))
         hr = setError(VBOX_E_IPRT_ERROR,
-                      tr("Error retrieving drag'n drop pending status (%Rrc)\n"), rc);
+                      tr("Error retrieving drag and drop pending status (%Rrc)\n"), rc);
 
     LogFlowFunc(("hr=%Rhrc, defaultAction=0x%x\n", hr, defaultAction));
@@ -289,6 +287,5 @@
 }
 
-HRESULT GuestDnDSource::drop(const com::Utf8Str &aFormat,
-                             DnDAction_T aAction, ComPtr<IProgress> &aProgress)
+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)
@@ -308,4 +305,5 @@
         return S_OK;
 
+    /* Note: At the moment we only support one transfer at a time. */
     if (ASMAtomicReadBool(&mData.mfDropIsPending))
         return setError(E_INVALIDARG, tr("Another drop operation already is in progress"));
@@ -313,43 +311,41 @@
     ASMAtomicWriteBool(&mData.mfDropIsPending, true);
 
-    HRESULT hr = S_OK;
-
-    /* Note: At the moment we only support one response at a time. */
+    /* Dito. */
     GuestDnDResponse *pResp = GuestDnDInst()->response();
-    if (pResp)
-    {
-        pResp->resetProgress(m_pGuest);
-
-        int rc;
-
-        try
-        {
-            mData.mRecvCtx.mpSource = this;
-            mData.mRecvCtx.mpResp   = pResp;
-            mData.mRecvCtx.mFormat  = aFormat;
-
-            RecvDataTask *pTask = new RecvDataTask(this, &mData.mRecvCtx);
-            AssertReturn(pTask->isOk(), pTask->getRC());
-
-            rc = RTThreadCreate(NULL, GuestDnDSource::i_receiveDataThread,
+    AssertPtr(pResp);
+
+    HRESULT hr = pResp->resetProgress(m_pGuest);
+    if (FAILED(hr))
+        return hr;
+
+    try
+    {
+        mData.mRecvCtx.mIsActive = false;
+        mData.mRecvCtx.mpSource  = this;
+        mData.mRecvCtx.mpResp    = pResp;
+        mData.mRecvCtx.mFormat   = aFormat;
+
+        RecvDataTask *pTask = new RecvDataTask(this, &mData.mRecvCtx);
+        AssertReturn(pTask->isOk(), pTask->getRC());
+
+        RTTHREAD recvThread;
+        int rc = RTThreadCreate(&recvThread, GuestDnDSource::i_receiveDataThread,
                                 (void *)pTask, 0, RTTHREADTYPE_MAIN_WORKER, 0, "dndSrcRcvData");
-            if (RT_SUCCESS(rc))
-            {
-                hr = pResp->queryProgressTo(aProgress.asOutParam());
-                ComAssertComRC(hr);
-
-                /* Note: pTask is now owned by the worker thread. */
-            }
-        }
-        catch(std::bad_alloc &)
-        {
-            rc = VERR_NO_MEMORY;
-        }
-
-        /*if (RT_FAILURE(vrc)) @todo SetError(...) */
-    }
-    /** @todo SetError(...) */
-
-    ASMAtomicWriteBool(&mData.mfDropIsPending, false);
+        if (RT_SUCCESS(rc))
+        {
+            hr = pResp->queryProgressTo(aProgress.asOutParam());
+            ComAssertComRC(hr);
+
+            /* Note: pTask is now owned by the worker thread. */
+        }
+        else
+            hr = setError(VBOX_E_IPRT_ERROR, tr("Starting thread failed (%Rrc)"), rc);
+    }
+    catch(std::bad_alloc &)
+    {
+        hr = setError(E_OUTOFMEMORY);
+    }
+
+    /* Note: mData.mfDropIsPending will be set to false again by i_receiveDataThread. */
 
     LogFlowFunc(("Returning hr=%Rhrc\n", hr));
@@ -680,5 +676,5 @@
 #endif /* VBOX_WITH_DRAG_AND_DROP_GH */
 
-int GuestDnDSource::i_receiveData(PRECVDATACTX pCtx)
+int GuestDnDSource::i_receiveData(PRECVDATACTX pCtx, RTMSINTERVAL msTimeout)
 {
     AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
@@ -691,4 +687,8 @@
     AssertPtr(pCtx->mpResp);
 
+    /* Is this context already in receiving state? */
+    if (ASMAtomicReadBool(&pCtx->mIsActive))
+        return VERR_WRONG_ORDER;
+
     ASMAtomicWriteBool(&pCtx->mIsActive, true);
 
@@ -697,31 +697,28 @@
         return rc;
 
+    /*
+     * Reset any old data.
+     */
     pCtx->mData.vecData.clear();
     pCtx->mData.cbToProcess = 0;
     pCtx->mData.cbProcessed = 0;
 
-    do
-    {
-        /* 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(pCtx->mFormat);
-
-        bool fHasURIList = DnDMIMENeedsDropDir(pCtx->mFormat.c_str(), pCtx->mFormat.length());
-        LogFlowFunc(("strFormat=%s, uAction=0x%x, fHasURIList=%RTbool\n", pCtx->mFormat.c_str(), pCtx->mAction, fHasURIList));
-
-        if (fHasURIList)
-        {
-            rc = i_receiveURIData(pCtx);
-        }
-        else
-        {
-            rc = i_receiveRawData(pCtx);
-        }
-
-    } while (0);
+    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(pCtx->mFormat);
+
+    bool fHasURIList = DnDMIMENeedsDropDir(pCtx->mFormat.c_str(), pCtx->mFormat.length());
+    LogFlowFunc(("strFormat=%s, uAction=0x%x, fHasURIList=%RTbool\n", pCtx->mFormat.c_str(), pCtx->mAction, fHasURIList));
+    if (fHasURIList)
+    {
+        rc = i_receiveURIData(pCtx, msTimeout);
+    }
+    else
+    {
+        rc = i_receiveRawData(pCtx, msTimeout);
+    }
 
     ASMAtomicWriteBool(&pCtx->mIsActive, false);
@@ -747,5 +744,5 @@
     if (SUCCEEDED(autoCaller.rc()))
     {
-        rc = pSource->i_receiveData(pTask->getCtx());
+        rc = pSource->i_receiveData(pTask->getCtx(), RT_INDEFINITE_WAIT);
     }
     else
@@ -756,8 +753,11 @@
     if (pTask)
         delete pTask;
+
+    ASMAtomicWriteBool(&pSource->mData.mfDropIsPending, false);
+
     return rc;
 }
 
-int GuestDnDSource::i_receiveRawData(PRECVDATACTX pCtx)
+int GuestDnDSource::i_receiveRawData(PRECVDATACTX pCtx, RTMSINTERVAL msTimeout)
 {
     AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
@@ -807,6 +807,6 @@
              * wait event.
              */
-            LogFlowFunc(("Waiting for raw data callback ...\n"));
-            rc = pCtx->mCallback.Wait(RT_INDEFINITE_WAIT);
+            LogFlowFunc(("Waiting for raw data callback (%RU32ms timeout) ...\n", msTimeout));
+            rc = pCtx->mCallback.Wait(msTimeout);
             LogFlowFunc(("Raw callback done, rc=%Rrc\n", rc));
         }
@@ -827,5 +827,5 @@
 }
 
-int GuestDnDSource::i_receiveURIData(PRECVDATACTX pCtx)
+int GuestDnDSource::i_receiveURIData(PRECVDATACTX pCtx, RTMSINTERVAL msTimeout)
 {
     AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
@@ -888,6 +888,6 @@
              * wait event.
              */
-            LogFlowFunc(("Waiting for URI callback ...\n"));
-            rc = pCtx->mCallback.Wait(RT_INDEFINITE_WAIT);
+            LogFlowFunc(("Waiting for URI callback (%RU32ms timeout) ...\n", msTimeout));
+            rc = pCtx->mCallback.Wait(msTimeout);
             LogFlowFunc(("URI callback done, rc=%Rrc\n", rc));
         }
Index: trunk/src/VBox/Main/src-client/GuestDnDTargetImpl.cpp
===================================================================
--- trunk/src/VBox/Main/src-client/GuestDnDTargetImpl.cpp	(revision 55535)
+++ trunk/src/VBox/Main/src-client/GuestDnDTargetImpl.cpp	(revision 55539)
@@ -22,5 +22,4 @@
 #include "GuestImpl.h"
 #include "GuestDnDTargetImpl.h"
-#include "VirtualBoxErrorInfoImpl.h"
 
 #include "Global.h"
@@ -528,48 +527,48 @@
     if (FAILED(autoCaller.rc())) return autoCaller.rc();
 
-    HRESULT hr = S_OK;
-    int vrc;
-
     /* Note: At the moment we only support one response at a time. */
     GuestDnDResponse *pResp = GuestDnDInst()->response();
-    if (pResp)
-    {
-        pResp->resetProgress(m_pGuest);
-
-        try
-        {
-            PSENDDATACTX pSendCtx = new SENDDATACTX;
-            RT_BZERO(pSendCtx, sizeof(SENDDATACTX));
-
-            pSendCtx->mpTarget      = this;
-            pSendCtx->mpResp        = pResp;
-            pSendCtx->mScreenID     = aScreenId;
-            pSendCtx->mFormat       = aFormat;
-            pSendCtx->mData.vecData = aData;
-
-            SendDataTask *pTask = new SendDataTask(this, pSendCtx);
-            AssertReturn(pTask->isOk(), pTask->getRC());
-
-            vrc = RTThreadCreate(NULL, GuestDnDTarget::i_sendDataThread,
-                                 (void *)pTask, 0, RTTHREADTYPE_MAIN_WORKER, 0, "dndTgtSndData");
-            if (RT_SUCCESS(vrc))
-            {
-                hr = pResp->queryProgressTo(aProgress.asOutParam());
-                ComAssertComRC(hr);
-
-                /* Note: pTask is now owned by the worker thread. */
-            }
-            else if (pSendCtx)
-                delete pSendCtx;
-        }
-        catch(std::bad_alloc &)
-        {
-            vrc = VERR_NO_MEMORY;
-        }
-
-        /*if (RT_FAILURE(vrc)) ** @todo SetError(...) */
-    }
-    /** @todo SetError(...) */
-
+    AssertPtr(pResp);
+
+    HRESULT hr = pResp->resetProgress(m_pGuest);
+    if (FAILED(hr))
+        return hr;
+
+    try
+    {
+        PSENDDATACTX pSendCtx = new SENDDATACTX;
+        RT_BZERO(pSendCtx, sizeof(SENDDATACTX));
+
+        pSendCtx->mpTarget      = this;
+        pSendCtx->mpResp        = pResp;
+        pSendCtx->mScreenID     = aScreenId;
+        pSendCtx->mFormat       = aFormat;
+        pSendCtx->mData.vecData = aData;
+
+        SendDataTask *pTask = new SendDataTask(this, pSendCtx);
+        AssertReturn(pTask->isOk(), pTask->getRC());
+
+        RTTHREAD sendThread;
+        int rc = RTThreadCreate(&sendThread, GuestDnDTarget::i_sendDataThread,
+                                (void *)pTask, 0, RTTHREADTYPE_MAIN_WORKER, 0, "dndTgtSndData");
+        if (RT_SUCCESS(rc))
+        {
+            hr = pResp->queryProgressTo(aProgress.asOutParam());
+            ComAssertComRC(hr);
+
+            /* Note: pTask is now owned by the worker thread. */
+        }
+        else
+            hr = setError(VBOX_E_IPRT_ERROR, tr("Starting thread failed (%Rrc)"), rc);
+
+        if (RT_FAILURE(rc))
+            delete pSendCtx;
+    }
+    catch(std::bad_alloc &)
+    {
+        hr = setError(E_OUTOFMEMORY);
+    }
+
+    LogFlowFunc(("Returning hr=%Rhrc\n", hr));
     return hr;
 #endif /* VBOX_WITH_DRAG_AND_DROP */
@@ -963,5 +962,5 @@
      * Register callbacks.
      */
-    /* Generic callbacks. */
+    /* Guest callbacks. */
     REGISTER_CALLBACK(DragAndDropSvc::GUEST_DND_GET_NEXT_HOST_MSG);
     REGISTER_CALLBACK(DragAndDropSvc::GUEST_DND_GH_EVT_ERROR);
