Index: /trunk/include/VBox/HostServices/DragAndDropSvc.h
===================================================================
--- /trunk/include/VBox/HostServices/DragAndDropSvc.h	(revision 55538)
+++ /trunk/include/VBox/HostServices/DragAndDropSvc.h	(revision 55539)
@@ -607,7 +607,7 @@
 {
     /** Magic number to identify the structure. */
-    uint32_t u32Magic;
+    uint32_t                    u32Magic;
     /** Context ID to identify callback data. */
-    uint32_t u32ContextID;
+    uint32_t                    u32ContextID;
 } VBOXDNDCBHEADERDATA, *PVBOXDNDCBHEADERDATA;
 
@@ -615,7 +615,7 @@
 {
     /** Callback data header. */
-    VBOXDNDCBHEADERDATA hdr;
-    uint32_t uMsg;
-    uint32_t cParms;
+    VBOXDNDCBHEADERDATA         hdr;
+    uint32_t                    uMsg;
+    uint32_t                    cParms;
 } VBOXDNDCBHGGETNEXTHOSTMSG, *PVBOXDNDCBHGGETNEXTHOSTMSG;
 
@@ -623,8 +623,8 @@
 {
     /** Callback data header. */
-    VBOXDNDCBHEADERDATA hdr;
-    uint32_t uMsg;
-    uint32_t cParms;
-    PVBOXHGCMSVCPARM paParms;
+    VBOXDNDCBHEADERDATA         hdr;
+    uint32_t                    uMsg;
+    uint32_t                    cParms;
+    PVBOXHGCMSVCPARM            paParms;
 } VBOXDNDCBHGGETNEXTHOSTMSGDATA, *PVBOXDNDCBHGGETNEXTHOSTMSGDATA;
 
@@ -632,6 +632,6 @@
 {
     /** Callback data header. */
-    VBOXDNDCBHEADERDATA hdr;
-    uint32_t uAction;
+    VBOXDNDCBHEADERDATA         hdr;
+    uint32_t                    uAction;
 } VBOXDNDCBHGACKOPDATA, *PVBOXDNDCBHGACKOPDATA;
 
@@ -639,6 +639,7 @@
 {
     /** Callback data header. */
-    VBOXDNDCBHEADERDATA hdr;
-    char *pszFormat;
+    VBOXDNDCBHEADERDATA         hdr;
+    char                       *pszFormat;
+    uint32_t                    cbFormat;
 } VBOXDNDCBHGREQDATADATA, *PVBOXDNDCBHGREQDATADATA;
 
@@ -646,8 +647,8 @@
 {
     /** Callback data header. */
-    VBOXDNDCBHEADERDATA hdr;
-    uint32_t uPercentage;
-    uint32_t uStatus;
-    uint32_t rc;
+    VBOXDNDCBHEADERDATA         hdr;
+    uint32_t                    uPercentage;
+    uint32_t                    uStatus;
+    uint32_t                    rc;
 } VBOXDNDCBHGEVTPROGRESSDATA, *PVBOXDNDCBHGEVTPROGRESSDATA;
 
@@ -655,8 +656,9 @@
 {
     /** Callback data header. */
-    VBOXDNDCBHEADERDATA hdr;
-    uint32_t  uDefAction;
-    uint32_t  uAllActions;
-    char     *pszFormat;
+    VBOXDNDCBHEADERDATA         hdr;
+    uint32_t                    uDefAction;
+    uint32_t                    uAllActions;
+    char                       *pszFormat;
+    uint32_t                    cbFormat;
 } VBOXDNDCBGHACKPENDINGDATA, *PVBOXDNDCBGHACKPENDINGDATA;
 
@@ -664,10 +666,10 @@
 {
     /** Callback data header. */
-    VBOXDNDCBHEADERDATA hdr;
-    void     *pvData;
-    uint32_t  cbData;
+    VBOXDNDCBHEADERDATA         hdr;
+    void                       *pvData;
+    uint32_t                    cbData;
     /** Total metadata size (in bytes). This is transmitted
      *  with every message because the size can change. */
-    uint32_t  cbTotalSize;
+    uint32_t                    cbTotalSize;
 } VBOXDNDCBSNDDATADATA, *PVBOXDNDCBSNDDATADATA;
 
@@ -675,8 +677,8 @@
 {
     /** Callback data header. */
-    VBOXDNDCBHEADERDATA hdr;
-    char     *pszPath;
-    uint32_t  cbPath;
-    uint32_t  fMode;
+    VBOXDNDCBHEADERDATA         hdr;
+    char                       *pszPath;
+    uint32_t                    cbPath;
+    uint32_t                    fMode;
 } VBOXDNDCBSNDDIRDATA, *PVBOXDNDCBSNDDIRDATA;
 
@@ -685,15 +687,15 @@
 {
     /** Callback data header. */
-    VBOXDNDCBHEADERDATA hdr;
+    VBOXDNDCBHEADERDATA         hdr;
     /** File path (name). */
-    char     *pszFilePath;
+    char                       *pszFilePath;
     /** Size (in bytes) of file path. */
-    uint32_t  cbFilePath;
+    uint32_t                    cbFilePath;
     /** Total size (in bytes) of this file. */
-    uint64_t  cbSize;
+    uint64_t                    cbSize;
     /** File (creation) mode. */
-    uint32_t  fMode;
+    uint32_t                    fMode;
     /** Additional flags. Not used at the moment. */
-    uint32_t  fFlags;
+    uint32_t                    fFlags;
 } VBOXDNDCBSNDFILEHDRDATA, *PVBOXDNDCBSNDFILEHDRDATA;
 
@@ -701,9 +703,9 @@
 {
     /** Callback data header. */
-    VBOXDNDCBHEADERDATA  hdr;
+    VBOXDNDCBHEADERDATA         hdr;
     /** Current file data chunk. */
-    void                *pvData;
+    void                       *pvData;
     /** Size (in bytes) of current data chunk. */
-    uint32_t             cbData;
+    uint32_t                    cbData;
     union
     {
@@ -711,9 +713,9 @@
         {
             /** File path (name). */
-            char     *pszFilePath;
+            char               *pszFilePath;
             /** Size (in bytes) of file path. */
-            uint32_t  cbFilePath;
+            uint32_t            cbFilePath;
             /** File (creation) mode. */
-            uint32_t  fMode;
+            uint32_t            fMode;
         } v1;
         /* Note: Protocol version 2 has the file attributes (name, size,
@@ -725,6 +727,6 @@
 {
     /** Callback data header. */
-    VBOXDNDCBHEADERDATA hdr;
-    int32_t rc;
+    VBOXDNDCBHEADERDATA         hdr;
+    int32_t                     rc;
 } VBOXDNDCBEVTERRORDATA, *PVBOXDNDCBEVTERRORDATA;
 
Index: /trunk/src/VBox/Frontends/VirtualBox/src/globals/UIMessageCenter.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VirtualBox/src/globals/UIMessageCenter.cpp	(revision 55538)
+++ /trunk/src/VBox/Frontends/VirtualBox/src/globals/UIMessageCenter.cpp	(revision 55539)
@@ -73,4 +73,5 @@
 # ifdef VBOX_WITH_DRAG_AND_DROP
 #  include "CGuest.h"
+#  include "CDnDSource.h"
 #  include "CDnDTarget.h"
 # endif /* VBOX_WITH_DRAG_AND_DROP */
@@ -2399,23 +2400,37 @@
 
 #ifdef VBOX_WITH_DRAG_AND_DROP
-void UIMessageCenter::cannotDropData(const CGuest &guest, QWidget *pParent /* = 0*/) const
-{
-    error(pParent, MessageType_Error,
-          tr("Drag and drop operation failed."),
-          formatErrorInfo(guest));
-}
-
-void UIMessageCenter::cannotDropData(const CProgress &progress, QWidget *pParent /* = 0*/) const
-{
-    error(pParent, MessageType_Error,
-          tr("Failed while dropping data."),
+void UIMessageCenter::cannotDropDataToGuest(const CDnDTarget &dndTarget, QWidget *pParent /* = 0*/) const
+{
+    error(pParent, MessageType_Error,
+          tr("Drag and drop operation from host to guest failed."),
+          formatErrorInfo(dndTarget));
+}
+
+void UIMessageCenter::cannotDropDataToGuest(const CProgress &progress, QWidget *pParent /* = 0*/) const
+{
+    error(pParent, MessageType_Error,
+          tr("Drag and drop operation from host to guest failed."),
           formatErrorInfo(progress));
 }
 
-void UIMessageCenter::cannotCancelDrop(const CDnDTarget &dndTarget, QWidget *pParent /* = 0*/) const
-{
-    error(pParent, MessageType_Error,
-          tr("Unable to cancel drag and drop operation."),
+void UIMessageCenter::cannotCancelDropToGuest(const CDnDTarget &dndTarget, QWidget *pParent /* = 0*/) const
+{
+    error(pParent, MessageType_Error,
+          tr("Unable to cancel host to guest drag and drop operation."),
           formatErrorInfo(dndTarget));
+}
+
+void UIMessageCenter::cannotDropDataToHost(const CDnDSource &dndSource, QWidget *pParent /* = 0*/) const
+{
+    error(pParent, MessageType_Error,
+          tr("Drag and drop operation from guest to host failed."),
+          formatErrorInfo(dndSource));
+}
+
+void UIMessageCenter::cannotDropDataToHost(const CProgress &progress, QWidget *pParent /* = 0*/) const
+{
+    error(pParent, MessageType_Error,
+          tr("Drag and drop operation from guest to host failed."),
+          formatErrorInfo(progress));
 }
 #endif /* VBOX_WITH_DRAG_AND_DROP */
Index: /trunk/src/VBox/Frontends/VirtualBox/src/globals/UIMessageCenter.h
===================================================================
--- /trunk/src/VBox/Frontends/VirtualBox/src/globals/UIMessageCenter.h	(revision 55538)
+++ /trunk/src/VBox/Frontends/VirtualBox/src/globals/UIMessageCenter.h	(revision 55539)
@@ -349,8 +349,11 @@
 
 #ifdef VBOX_WITH_DRAG_AND_DROP
-    /* API: Drag&drop warnings: */
-    void cannotDropData(const CGuest &guest, QWidget *pParent = 0) const;
-    void cannotDropData(const CProgress &progress, QWidget *pParent = 0) const;
-    void cannotCancelDrop(const CDnDTarget &dndTarget, QWidget *pParent = 0) const;
+    /* API: Drag and drop errors: Host -> Guest */
+    void cannotDropDataToGuest(const CDnDTarget &dndTarget, QWidget *pParent = 0) const;
+    void cannotCancelDropToGuest(const CDnDTarget &dndTarget, QWidget *pParent = 0) const;
+    void cannotDropDataToGuest(const CProgress &progress, QWidget *pParent /* = 0*/) const;
+    /* API: Drag and drop errors: Guest -> Host */
+    void cannotDropDataToHost(const CDnDSource &dndSource, QWidget *pParent = 0) const;
+    void cannotDropDataToHost(const CProgress &progress, QWidget *pParent /* = 0*/) const;
 #endif /* VBOX_WITH_DRAG_AND_DROP */
 
Index: /trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIDnDDrag.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIDnDDrag.cpp	(revision 55538)
+++ /trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIDnDDrag.cpp	(revision 55539)
@@ -151,5 +151,5 @@
     CProgress progress = dndSource.Drop(strMimeType,
                                         UIDnDHandler::toVBoxDnDAction(dropAction));
-    if (guest.isOk())
+    if (dndSource.isOk())
     {
         msgCenter().showModalProgressDialog(progress,
@@ -201,5 +201,5 @@
             }
             else
-                msgCenter().cannotDropData(progress, pParent);
+                msgCenter().cannotDropDataToHost(progress, pParent);
         }
         else /* Don't pop up a message. */
@@ -208,5 +208,5 @@
     else
     {
-        msgCenter().cannotDropData(guest, pParent);
+        msgCenter().cannotDropDataToHost(dndSource, pParent);
         rc = VERR_GENERAL_FAILURE; /** @todo Fudge; do a GetResultCode() to rc translation. */
     }
Index: /trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIDnDHandler.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIDnDHandler.cpp	(revision 55538)
+++ /trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIDnDHandler.cpp	(revision 55539)
@@ -134,5 +134,5 @@
             CProgress progress = dndTarget.SendData(screenId, format, dv);
 
-            if (progress.isOk())
+            if (dndTarget.isOk())
             {
                 LogFlowFunc(("Transferring data to guest ...\n"));
@@ -146,29 +146,15 @@
 
                 BOOL fCanceled = progress.GetCanceled();
-
-                /* Some error occurred? */
                 if (   !fCanceled
                     && (   !progress.isOk()
                         ||  progress.GetResultCode() != 0))
                 {
-                    msgCenter().cannotDropData(progress, pParent);
+                    msgCenter().cannotDropDataToGuest(progress, pParent);
                     result = KDnDAction_Ignore;
                 }
-                #if 0
-                else if (fCanceled) /* Operation canceled by user? */
-                {
-                    Assert(progress.isOk());
-                    Assert(progress.GetResultCode() == 0);
-
-                    /* Tell the guest. */
-                    BOOL fVeto = dndTarget.Cancel();
-                    if (fVeto) /* Cancelling vetoed by the target? Tell the user why. */
-                        msgCenter().cannotCancelDrop(dndTarget, pParent);
-                }
-                #endif
             }
             else
             {
-                msgCenter().cannotDropData(guest, pParent);
+                msgCenter().cannotDropDataToGuest(dndTarget, pParent);
                 result = KDnDAction_Ignore;
             }
Index: /trunk/src/VBox/HostServices/DragAndDrop/service.cpp
===================================================================
--- /trunk/src/VBox/HostServices/DragAndDrop/service.cpp	(revision 55538)
+++ /trunk/src/VBox/HostServices/DragAndDrop/service.cpp	(revision 55539)
@@ -480,8 +480,5 @@
                         rc = paParms[1].getUInt32(&data.uAllActions);
                     if (RT_SUCCESS(rc))
-                    {
-                        uint32_t cTmp;
-                        rc = paParms[2].getPointer((void**)&data.pszFormat, &cTmp);
-                    }
+                        rc = paParms[2].getPointer((void**)&data.pszFormat, &data.cbFormat);
                     DO_HOST_CALLBACK();
                 }
Index: /trunk/src/VBox/Main/include/GuestDnDSourceImpl.h
===================================================================
--- /trunk/src/VBox/Main/include/GuestDnDSourceImpl.h	(revision 55538)
+++ /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 55538)
+++ /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 55538)
+++ /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 55538)
+++ /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);
