Index: trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxDnD.cpp
===================================================================
--- trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxDnD.cpp	(revision 50560)
+++ trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxDnD.cpp	(revision 50561)
@@ -60,4 +60,5 @@
 VBoxDnDWnd::VBoxDnDWnd(void)
     : hWnd(NULL),
+      uAllActions(DND_IGNORE_ACTION),
       mfMouseButtonDown(false),
 #ifdef VBOX_WITH_DRAG_AND_DROP_GH
@@ -69,6 +70,4 @@
 {
     RT_ZERO(startupInfo);
-
-    reset();
 }
 
@@ -209,5 +208,5 @@
     else
     {
-        LogRelFunc(("Unable to initialize OLE, hr=%Rhrc\n", hr));
+        LogRel(("DnD: Unable to initialize OLE, hr=%Rhrc\n", hr));
         rc = VERR_COM_UNEXPECTED;
     }
@@ -380,6 +379,4 @@
             else if (mMode == GH) /* Guest to host. */
             {
-                //hide();
-
                 /* Starting here VBoxDnDDropTarget should
                  * take over; was instantiated when registering
@@ -405,5 +402,6 @@
         {
             VBOXDNDEVENT *pEvent = (PVBOXDNDEVENT)lParam;
-            AssertPtr(pEvent);
+            if (!pEvent)
+                break; /* No event received, bail out. */
 
             LogFlowThisFunc(("Received uType=%RU32, uScreenID=%RU32\n",
@@ -416,8 +414,4 @@
                 {
                     LogFlowThisFunc(("HOST_DND_HG_EVT_ENTER\n"));
-
-                    reset();
-
-                    mMode = HG;
 
                     if (pEvent->Event.cbFormats)
@@ -484,14 +478,6 @@
                     LogFlowThisFunc(("HOST_DND_GH_REQ_PENDING\n"));
 #ifdef VBOX_WITH_DRAG_AND_DROP_GH
-                    if (   mMode == Unknown
-                        /* There can be more than one HOST_DND_GH_REQ_PENDING
-                         * messages coming in. */
-                        || mMode == GH)
-                    {
-                        mMode = GH;
-                        rc = OnGhIsDnDPending(pEvent->Event.uScreenId);
-                    }
-                    else
-                        rc = VERR_WRONG_ORDER;
+                    rc = OnGhIsDnDPending(pEvent->Event.uScreenId);
+
 #else
                     rc = VERR_NOT_SUPPORTED;
@@ -504,60 +490,7 @@
                     LogFlowThisFunc(("HOST_DND_GH_EVT_DROPPED\n"));
 #ifdef VBOX_WITH_DRAG_AND_DROP_GH
-                    if (mMode == GH)
-                    {
-                        rc = OnGhDropped(pEvent->Event.pszFormats,
-                                         pEvent->Event.cbFormats,
-                                         pEvent->Event.u.a.uDefAction);
-                    }
-                    else
-                        rc = VERR_WRONG_ORDER;
-#else
-                    rc = VERR_NOT_SUPPORTED;
-#endif
-                    break;
-                }
-
-                case DragAndDropSvc::GUEST_DND_GH_EVT_ERROR:
-                {
-                    LogFlowThisFunc(("GUEST_DND_GH_EVT_ERROR\n"));
-#ifdef VBOX_WITH_DRAG_AND_DROP_GH
-                    reset();
-                    rc = VINF_SUCCESS; /** @todo GUEST_DND_GH_EVT_ERROR */
-#else
-                    rc = VERR_NOT_SUPPORTED;
-#endif
-                    break;
-                }
-
-                case DragAndDropSvc::HOST_DND_GH_RECV_DIR:
-                {
-                    LogFlowThisFunc(("HOST_DND_GH_RECV_DIR\n"));
-#ifdef VBOX_WITH_DRAG_AND_DROP_GH
-                    if (mMode == GH)
-                    {
-                        rc = OnGhSendDir(pEvent->Event.pszFormats,
-                                         pEvent->Event.cbFormats,
-                                         pEvent->Event.u.a.uDefAction);
-                    }
-                    else
-                        rc = VERR_WRONG_ORDER;
-#else
-                    rc = VERR_NOT_SUPPORTED;
-#endif
-                    break;
-                }
-
-                case DragAndDropSvc::HOST_DND_GH_RECV_FILE:
-                {
-                    LogFlowThisFunc(("HOST_DND_GH_RECV_FILE\n"));
-#ifdef VBOX_WITH_DRAG_AND_DROP_GH
-                    if (mMode == GH)
-                    {
-                        rc = OnGhSendFile(pEvent->Event.pszFormats,
-                                          pEvent->Event.cbFormats,
-                                          pEvent->Event.u.a.uDefAction);
-                    }
-                    else
-                        rc = VERR_WRONG_ORDER;
+                    rc = OnGhDropped(pEvent->Event.pszFormats,
+                                     pEvent->Event.cbFormats,
+                                     pEvent->Event.u.a.uDefAction);
 #else
                     rc = VERR_NOT_SUPPORTED;
@@ -600,8 +533,11 @@
             }
 
-            LogFlowThisFunc(("Processing event %RU32 resulted in rc=%Rrc\n",
-                             pEvent->Event.uType, rc));
             if (pEvent)
+            {
+                LogFlowThisFunc(("Processing event %RU32 resulted in rc=%Rrc\n",
+                                 pEvent->Event.uType, rc));
+
                 RTMemFree(pEvent);
+            }
             return 0;
         }
@@ -702,4 +638,7 @@
 int VBoxDnDWnd::OnHgEnter(const RTCList<RTCString> &lstFormats, uint32_t uAllActions)
 {
+    if (mMode == GH) /* Wrong mode? Bail out. */
+        return VERR_WRONG_ORDER;
+
 #ifdef DEBUG
     LogFlowThisFunc(("uActions=0x%x, lstFormats=%zu: ", uAllActions, lstFormats.size()));
@@ -708,4 +647,7 @@
     LogFlow(("\n"));
 #endif
+
+    reset();
+    setMode(HG);
 
     /* Save all allowed actions. */
@@ -779,20 +721,27 @@
 int VBoxDnDWnd::OnHgMove(uint32_t u32xPos, uint32_t u32yPos, uint32_t uAction)
 {
-    LogFlowThisFunc(("u32xPos=%RU32, u32yPos=%RU32, uAction=0x%x\n",
-                     u32xPos, u32yPos, uAction));
-
-    int rc = mouseMove(u32xPos, u32yPos, MOUSEEVENTF_LEFTDOWN);
+    int rc;
 
     uint32_t uActionNotify = DND_IGNORE_ACTION;
-    if (RT_SUCCESS(rc))
-        rc = RTCritSectEnter(&mCritSect);
-    if (RT_SUCCESS(rc))
-    {
-        if (   (Dragging == mState)
-            && startupInfo.pDropSource)
-            uActionNotify = startupInfo.pDropSource->GetCurrentAction();
-
-        RTCritSectLeave(&mCritSect);
-    }
+    if (mMode == HG)
+    {
+        LogFlowThisFunc(("u32xPos=%RU32, u32yPos=%RU32, uAction=0x%x\n",
+                         u32xPos, u32yPos, uAction));
+
+        rc = mouseMove(u32xPos, u32yPos, MOUSEEVENTF_LEFTDOWN);
+
+        if (RT_SUCCESS(rc))
+            rc = RTCritSectEnter(&mCritSect);
+        if (RT_SUCCESS(rc))
+        {
+            if (   (Dragging == mState)
+                && startupInfo.pDropSource)
+                uActionNotify = startupInfo.pDropSource->GetCurrentAction();
+
+            RTCritSectLeave(&mCritSect);
+        }
+    }
+    else /* Just acknowledge the operation with an ignore action. */
+        rc = VINF_SUCCESS;
 
     if (RT_SUCCESS(rc))
@@ -809,4 +758,7 @@
 int VBoxDnDWnd::OnHgLeave(void)
 {
+    if (mMode == GH) /* Wrong mode? Bail out. */
+        return VERR_WRONG_ORDER;
+
     LogFlowThisFunc(("mMode=%ld, mState=%RU32\n", mMode, mState));
     LogRel(("DnD: Drag'n drop operation aborted\n"));
@@ -826,4 +778,7 @@
 int VBoxDnDWnd::OnHgDrop(void)
 {
+    if (mMode == GH)
+        return VERR_WRONG_ORDER;
+
     LogFlowThisFunc(("mMode=%ld, mState=%RU32\n", mMode, mState));
 
@@ -917,6 +872,15 @@
                      mMode, mState, uScreenID));
 
+    if (mMode == Unknown)
+        setMode(GH);
+
+    if (mMode != GH)
+        return VERR_WRONG_ORDER;
+
     if (mState == Uninitialized)
-        reset();
+    {
+        /* Nothing to do here yet. */
+        mState = Initialized;
+    }
 
     int rc;
@@ -954,5 +918,5 @@
 
     if (   RT_SUCCESS(rc)
-        && (mState == Dragging))
+        && mState == Dragging)
     {
         /** @todo Put this block into a function! */
@@ -987,4 +951,5 @@
         {
             uDefAction = DND_COPY_ACTION;
+            /** @todo Support more than one action at a time. */
             uAllActions = uDefAction;
 
@@ -993,4 +958,27 @@
             rc = VbglR3DnDGHAcknowledgePending(mClientID,
                                                uDefAction, uAllActions, strFormats.c_str());
+            if (RT_FAILURE(rc))
+            {
+                char szMsg[256]; /* Sizes according to MSDN. */
+                char szTitle[64];
+
+                /** @todo Add some translation macros here. */
+                RTStrPrintf(szTitle, sizeof(szTitle), "VirtualBox Guest Additions Drag'n Drop");
+                RTStrPrintf(szMsg, sizeof(szMsg), "Drag'n drop to the host either is not supported or disabled. "
+                                                  "Pleas enable Guest to Host or Bidirectional drag'n drop mode "
+                                                  "or re-install the VirtualBox Guest Additions.");
+                switch (rc)
+                {
+                    case VERR_ACCESS_DENIED:
+                        rc = hlpShowBalloonTip(ghInstance, ghwndToolWindow, ID_TRAYICON,
+                                               szMsg, szTitle,
+                                               15 * 1000 /* Time to display in msec */, NIIF_INFO);
+                        AssertRC(rc);
+                        break;
+
+                    default:
+                        break;
+                }
+            }
         }
         else
@@ -1010,10 +998,21 @@
     LogFlowThisFunc(("mMode=%ld, mState=%ld, pDropTarget=0x%p, pszFormat=%s, uDefAction=0x%x\n",
                      mMode, mState, pDropTarget, pszFormat, uDefAction));
-
     int rc;
-    if (mState == Dragging)
-    {
-        AssertPtr(pDropTarget);
-        rc = pDropTarget->WaitForDrop(30 * 1000 /* Timeout in ms */);
+    if (mMode == GH)
+    {
+        if (mState == Dragging)
+        {
+            AssertPtr(pDropTarget);
+            rc = pDropTarget->WaitForDrop(30 * 1000 /* Timeout in ms */);
+
+            reset();
+        }
+        else if (mState == Dropped)
+        {
+            rc = VINF_SUCCESS;
+        }
+        else
+            rc = VERR_WRONG_ORDER;
+
         if (RT_SUCCESS(rc))
         {
@@ -1027,27 +1026,11 @@
             LogFlowFunc(("Sent pvData=0x%p, cbData=%RU32, rc=%Rrc\n",
                          pvData, cbData, rc));
-        }
-
-        reset();
+
+
+        }
     }
     else
         rc = VERR_WRONG_ORDER;
 
-    LogFlowFuncLeaveRC(rc);
-    return rc;
-}
-
-int VBoxDnDWnd::OnGhSendDir(const char *pszFormats, uint32_t cbFormats,
-                            uint32_t uDefAction)
-{
-    int rc = 0;
-    LogFlowFuncLeaveRC(rc);
-    return rc;
-}
-
-int VBoxDnDWnd::OnGhSendFile(const char *pszFormats, uint32_t cbFormats,
-                             uint32_t uDefAction)
-{
-    int rc = 0;
     LogFlowFuncLeaveRC(rc);
     return rc;
@@ -1213,5 +1196,6 @@
 void VBoxDnDWnd::reset(void)
 {
-    LogFlowThisFunc(("Old mState=%ld\n", mState));
+    LogFlowThisFunc(("Resetting, old mMode=%ld, mState=%ld\n",
+                     mMode, mState));
 
     lstAllowedFormats.clear();
@@ -1219,6 +1203,19 @@
     uAllActions = DND_IGNORE_ACTION;
 
-    mMode = Unknown;
+    int rc2 = setMode(Unknown);
+    AssertRC(rc2);
+
+    hide();
+}
+
+int VBoxDnDWnd::setMode(Mode enmMode)
+{
+    LogFlowThisFunc(("Old mode=%ld, new mode=%ld\n",
+                     mMode, enmMode));
+
+    mMode = enmMode;
     mState = Initialized;
+
+    return VINF_SUCCESS;
 }
 
@@ -1425,4 +1422,5 @@
             if (RT_FAILURE(rc2))
                 LogFlowFunc(("Cancelling failed with rc=%Rrc\n", rc2));
+            break;
         }
         else
@@ -1433,11 +1431,12 @@
              * don't support the stuff we do on the guest side, so make sure we
              * don't process invalid messages forever. */
-            if (rc == VERR_INVALID_PARAMETER)
-                cMsgSkippedInvalid++;
-            if (cMsgSkippedInvalid > 3)
+            if (cMsgSkippedInvalid++ > 3)
             {
-                LogFlowFunc(("Too many invalid/skipped messages from host, exiting ...\n"));
+                LogRel(("DnD: Too many invalid/skipped messages from host, exiting ...\n"));
                 break;
             }
+
+            int rc2 = VbglR3DnDGHSendError(uClientID, rc);
+            AssertRC(rc2);
         }
 
@@ -1445,4 +1444,7 @@
             break;
 
+        if (RT_FAILURE(rc)) /* Don't hog the CPU on errors. */
+            RTThreadSleep(1000 /* ms */);
+
     } while (true);
 
Index: trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxDnD.h
===================================================================
--- trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxDnD.h	(revision 50560)
+++ trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxDnD.h	(revision 50561)
@@ -340,6 +340,4 @@
     int OnGhIsDnDPending(uint32_t uScreenID);
     int OnGhDropped(const char *pszFormat, uint32_t cbFormats, uint32_t uDefAction);
-    int OnGhSendDir(const char *pszFormats, uint32_t cbFormats, uint32_t uDefAction);
-    int OnGhSendFile(const char *pszFormats, uint32_t cbFormats, uint32_t uDefAction);
 #endif
 
@@ -353,7 +351,8 @@
 
     int makeFullscreen(void);
-    void reset(void);
     int mouseMove(int x, int y, DWORD dwMouseInputFlags);
     int mouseRelease(void);
+    void reset(void);
+    int setMode(Mode enmMode);
 
 public: /** @todo Make protected! */
@@ -396,4 +395,5 @@
     /** The current state. */
     State                      mState;
+    bool                       mInFlight;
     RTCString                  mFormatRequested;
     RTCList<RTCString>         mLstFormats;
Index: trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxDnDDropTarget.cpp
===================================================================
--- trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxDnDDropTarget.cpp	(revision 50560)
+++ trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxDnDDropTarget.cpp	(revision 50561)
@@ -120,18 +120,29 @@
     else
     {
-        LogFlowFunc(("CF_HDROP not supported, hr=%Rhrc\n", hr));
+        LogFlowFunc(("CF_HDROP not wanted, hr=%Rhrc\n", hr));
 
         /* So we couldn't retrieve the data in CF_HDROP format; try with
-         * CF_TEXT format now. Rest stays the same. */
-        fmtEtc.cfFormat = CF_TEXT;
+         * CF_UNICODETEXT + CF_TEXT formats now. Rest stays the same. */
+        fmtEtc.cfFormat = CF_UNICODETEXT;
         hr = pDataObject->QueryGetData(&fmtEtc);
-        if (hr != S_OK)
+        if (hr == S_OK)
         {
-            LogFlowFunc(("CF_TEXT not supported, hr=%Rhrc\n", hr));
-            fmtEtc.cfFormat = 0; /* Mark it to not supported. */
+            mFormats = "text/plain;charset=utf-8";
         }
         else
         {
-            mFormats = "text/plain;charset=utf-8";
+            LogFlowFunc(("CF_UNICODETEXT not wanted, hr=%Rhrc\n", hr));
+
+            fmtEtc.cfFormat = CF_TEXT;
+            hr = pDataObject->QueryGetData(&fmtEtc);
+            if (hr == S_OK)
+            {
+                mFormats = "text/plain;charset=utf-8";
+            }
+            else
+            {
+                LogFlowFunc(("CF_TEXT not wanted, hr=%Rhrc\n", hr));
+                fmtEtc.cfFormat = 0; /* Mark it to not supported. */
+            }
         }
     }
@@ -306,6 +317,25 @@
                 switch (mFormatEtc.cfFormat)
                 {
-                    /* Handling CF_TEXT means that the system already did some marshalling
-                     * to convert RTF or unicode text to plain ANSI text. */
+                    case CF_UNICODETEXT:
+                    {
+                        AssertPtr(pvData);
+                        size_t cbSize = GlobalSize(pvData);
+                        LogFlowFunc(("CF_UNICODETEXT 0x%p got %zu bytes\n", pvData, cbSize));
+                        if (cbSize)
+                        {
+                            char *pszText = NULL;
+                            rc = RTUtf16ToUtf8((PCRTUTF16)pvData, &pszText);
+                            if (RT_SUCCESS(rc))
+                            {
+                                mpvData = (void *)pszText;
+                                mcbData = strlen(pszText) + 1; /* Include termination. */
+
+                                /* Note: Don't free data of pszText, mpvData now owns it. */
+                            }
+                        }
+
+                        break;
+                    }
+
                     case CF_TEXT:
                     {
@@ -320,5 +350,7 @@
                             {
                                 mpvData = (void *)pszText;
-                                mcbData = strlen(pszText) + 1;
+                                mcbData = strlen(pszText) + 1; /* Include termination. */
+
+                                /* Note: Don't free data of pszText, mpvData now owns it. */
                             }
                         }
@@ -412,11 +444,8 @@
                             /* Add separation between filenames.
                              * Note: Also do this for the last element of the list. */
-                            if (i > 0)
-                            {
-                                rc = RTStrAAppendExN(&pszFiles, 1 /* cPairs */,
-                                                     "\r\n", 2 /* Bytes */);
-                                if (RT_SUCCESS(rc))
-                                    cchFiles += 2; /* Include \r\n */
-                            }
+                            rc = RTStrAAppendExN(&pszFiles, 1 /* cPairs */,
+                                                 "\r\n", 2 /* Bytes */);
+                            if (RT_SUCCESS(rc))
+                                cchFiles += 2; /* Include \r\n */
                         }
 
Index: trunk/src/VBox/Additions/common/VBoxGuestLib/VBoxGuestR3LibDragAndDrop.cpp
===================================================================
--- trunk/src/VBox/Additions/common/VBoxGuestLib/VBoxGuestR3LibDragAndDrop.cpp	(revision 50560)
+++ trunk/src/VBox/Additions/common/VBoxGuestLib/VBoxGuestR3LibDragAndDrop.cpp	(revision 50561)
@@ -278,5 +278,5 @@
 
     /* Allocate temp buffer. */
-    uint32_t cbTmpData = _1M * 10; /** @todo r=andy 10MB, uh, really?? */
+    uint32_t cbTmpData = _64K; /** @todo Make this configurable? */
     void *pvTmpData = RTMemAlloc(cbTmpData);
     if (!pvTmpData)
@@ -311,6 +311,8 @@
     RTCList<RTCString> guestDirList;
     RTCList<RTCString> guestFileList;
-    char pszPathName[RTPATH_MAX];
-    uint32_t cbPathname = 0;
+
+    char szPathName[RTPATH_MAX];
+    uint32_t cbPathName = 0;
+
     bool fLoop = RT_SUCCESS(rc); /* No error occurred yet? */
     while (fLoop)
@@ -327,13 +329,17 @@
                     uint32_t fMode = 0;
                     rc = vbglR3DnDHGProcessSendDirMessage(uClientId,
-                                                          pszPathName,
-                                                          sizeof(pszPathName),
-                                                          &cbPathname,
+                                                          szPathName,
+                                                          sizeof(szPathName),
+                                                          &cbPathName,
                                                           &fMode);
+#ifdef DEBUG_andy
+                    LogFlowFunc(("HOST_DND_HG_SND_DIR pszPathName=%s, cbPathName=%RU32, fMode=0x%x, rc=%Rrc\n",
+                                 szPathName, cbPathName, fMode, rc));
+#endif
                     if (RT_SUCCESS(rc))
-                        rc = DnDPathSanitize(pszPathName, sizeof(pszPathName));
+                        rc = DnDPathSanitize(szPathName, sizeof(szPathName));
                     if (RT_SUCCESS(rc))
                     {
-                        char *pszNewDir = RTPathJoinA(pszDropDir, pszPathName);
+                        char *pszNewDir = RTPathJoinA(pszDropDir, szPathName);
                         if (pszNewDir)
                         {
@@ -354,17 +360,21 @@
                     uint32_t fMode = 0;
                     rc = vbglR3DnDHGProcessSendFileMessage(uClientId,
-                                                           pszPathName,
-                                                           sizeof(pszPathName),
-                                                           &cbPathname,
+                                                           szPathName,
+                                                           sizeof(szPathName),
+                                                           &cbPathName,
                                                            pvTmpData,
                                                            cbTmpData,
                                                            &cbDataRecv,
                                                            &fMode);
+#ifdef DEBUG_andy
+                    LogFlowFunc(("HOST_DND_HG_SND_FILE pszPathName=%s, cbPathName=%RU32, pvData=0x%p, cbDataRecv=%RU32, fMode=0x%x, rc=%Rrc\n",
+                                 szPathName, cbPathName, pvTmpData, cbDataRecv, fMode, rc));
+#endif
                     if (RT_SUCCESS(rc))
-                        rc = DnDPathSanitize(pszPathName, sizeof(pszPathName));
+                        rc = DnDPathSanitize(szPathName, sizeof(szPathName));
                     if (RT_SUCCESS(rc))
                     {
-                        char *pszNewFile = RTPathJoinA(pszDropDir, pszPathName);
-                        if (pszNewFile)
+                        char *pszPathAbs = RTPathJoinA(pszDropDir, szPathName);
+                        if (pszPathAbs)
                         {
                             RTFILE hFile;
@@ -372,5 +382,5 @@
                              *               create all sorts of funny races because we don't know if the guest has
                              *               modified the file in between the file data send calls. */
-                            rc = RTFileOpen(&hFile, pszNewFile,
+                            rc = RTFileOpen(&hFile, pszPathAbs,
                                             RTFILE_O_WRITE | RTFILE_O_APPEND | RTFILE_O_DENY_ALL | RTFILE_O_OPEN_CREATE);
                             if (RT_SUCCESS(rc))
@@ -386,10 +396,15 @@
                                         rc = RTFileSetMode(hFile, (fMode & RTFS_UNIX_MASK) | RTFS_UNIX_IRUSR | RTFS_UNIX_IWUSR);
                                 }
+
                                 RTFileClose(hFile);
-                                if (!guestFileList.contains(pszNewFile))
-                                    guestFileList.append(pszNewFile);
+
+                                if (!guestFileList.contains(pszPathAbs))
+                                    guestFileList.append(pszPathAbs);
                             }
-
-                            RTStrFree(pszNewFile);
+#ifdef DEBUG
+                            else
+                                LogFlowFunc(("Opening file failed with rc=%Rrc\n", rc));
+#endif
+                            RTStrFree(pszPathAbs);
                         }
                         else
@@ -416,4 +431,8 @@
             break;
         }
+
+        if (RT_FAILURE(rc))
+            break;
+
     } /* while */
 
@@ -430,4 +449,6 @@
             RTDirRemove(guestDirList.at(i).c_str());
         RTDirRemove(pszDropDir);
+
+        LogFlowFunc(("Failed with rc=%Rrc\n", rc));
     }
 
@@ -473,5 +494,5 @@
             rc = Msg.uScreenId.GetUInt32(puScreenId);  AssertRC(rc);
             rc = Msg.cFormat.GetUInt32(pcbFormatRecv); AssertRC(rc);
-            rc = Msg.cbData.GetUInt32(pcbDataTotal);     AssertRC(rc);
+            rc = Msg.cbData.GetUInt32(pcbDataTotal);   AssertRC(rc);
 
             AssertReturn(cbFormat >= *pcbFormatRecv, VERR_TOO_MUCH_DATA);
@@ -789,4 +810,16 @@
                 break;
             }
+            case DragAndDropSvc::HOST_DND_HG_SND_MORE_DATA:
+            case DragAndDropSvc::HOST_DND_HG_SND_DIR:
+            case DragAndDropSvc::HOST_DND_HG_SND_FILE:
+            {
+                pEvent->uType = uMsg;
+
+                /* All messages in this case are handled internally
+                 * by vbglR3DnDHGProcessSendDataMessage() and must
+                 * be specified by a preceding HOST_DND_HG_SND_DATA call. */
+                rc = VERR_WRONG_ORDER;
+                break;
+            }
             case DragAndDropSvc::HOST_DND_HG_EVT_CANCEL:
             {
@@ -1107,9 +1140,15 @@
         rc = vbglR3DnDGHSendDataInternal(u32ClientId, pvData, cbData,
                                          0 /* cbAdditionalData */);
-
-    return rc;
-}
-
-VBGLR3DECL(int) VbglR3DnDGHErrorEvent(uint32_t u32ClientId, int rcOp)
+    if (RT_FAILURE(rc))
+    {
+        int rc2 = VbglR3DnDGHSendError(u32ClientId, rc);
+        if (RT_SUCCESS(rc2))
+            rc2 = rc;
+    }
+
+    return rc;
+}
+
+VBGLR3DECL(int) VbglR3DnDGHSendError(uint32_t u32ClientId, int rcErr)
 {
     DragAndDropSvc::VBOXDNDGHEVTERRORMSG Msg;
@@ -1120,11 +1159,12 @@
     Msg.hdr.cParms      = 1;
 
-    Msg.uRC.SetUInt32(rcOp);
-
-    int rc = vbglR3DoIOCtl(VBOXGUEST_IOCTL_HGCM_CALL(sizeof(Msg)), &Msg, sizeof(Msg));
-    if (RT_SUCCESS(rc))
-        rc = Msg.hdr.result;
-
-    return rc;
-}
-
+    Msg.uRC.SetUInt32((uint32_t)rcErr); /* uint32_t vs. int. */
+
+    int rc = vbglR3DoIOCtl(VBOXGUEST_IOCTL_HGCM_CALL(sizeof(Msg)), &Msg, sizeof(Msg));
+    if (RT_SUCCESS(rc))
+        rc = Msg.hdr.result;
+
+    LogFlowFunc(("Sending error %Rrc returned with rc=%Rrc\n", rcErr, rc));
+    return rc;
+}
+
Index: trunk/src/VBox/Additions/x11/VBoxClient/draganddrop.cpp
===================================================================
--- trunk/src/VBox/Additions/x11/VBoxClient/draganddrop.cpp	(revision 50560)
+++ trunk/src/VBox/Additions/x11/VBoxClient/draganddrop.cpp	(revision 50561)
@@ -1317,5 +1317,5 @@
     /* Inform the host on error */
     if (RT_FAILURE(rc))
-        VbglR3DnDGHErrorEvent(rc);
+        VbglR3DnDGHSendError(rc);
 
     /* At this point, we have either successfully transfered any data or not.
Index: trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIDnDDataObject_win.cpp
===================================================================
--- trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIDnDDataObject_win.cpp	(revision 50560)
+++ trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIDnDDataObject_win.cpp	(revision 50561)
@@ -231,5 +231,4 @@
     if (mStatus == Dropped)
     {
-#ifdef VBOX_DND_DEBUG_FORMATS
         LogFlowFunc(("cfFormat=%RI16, sFormat=%s, tyMed=%RU32, dwAspect=%RU32\n",
                      pThisFormat->cfFormat, UIDnDDataObject::ClipboardFormatToString(pFormatEtc->cfFormat),
@@ -237,5 +236,5 @@
         LogFlowFunc(("Got strFormat=%s, pvData=%p, cbData=%RU32\n",
                      mstrFormat.toAscii().constData(), mpvData, mcbData));
-#endif
+
         QVariant::Type vaType;
         QString strMIMEType;
@@ -256,5 +255,5 @@
             vaType = QVariant::StringList;
         }
-#if 0
+#if 0 /* More formats; not needed right now. */
         else if (   (pFormatEtc->tymed & TYMED_ISTREAM)
                 && (pFormatEtc->dwAspect == DVASPECT_CONTENT)
@@ -285,16 +284,20 @@
                      strMIMEType.toAscii().constData(), vaType));
 
-        QVariant va;
-        int rc = mpParent->RetrieveData(strMIMEType, vaType, va);
+        int rc;
+        if (!mVaData.isValid())
+            rc = mpParent->RetrieveData(strMIMEType, vaType, mVaData);
+        else
+            rc = VINF_SUCCESS; /* Data already retrieved. */
+
         if (RT_SUCCESS(rc))
         {
             if (   strMIMEType.startsWith("text/uri-list")
                        /* One item. */
-                && (   va.canConvert(QVariant::String)
+                && (   mVaData.canConvert(QVariant::String)
                        /* Multiple items. */
-                    || va.canConvert(QVariant::StringList))
+                    || mVaData.canConvert(QVariant::StringList))
                )
             {
-                QStringList lstFilesURI = va.toStringList();
+                QStringList lstFilesURI = mVaData.toStringList();
                 QStringList lstFiles;
                 for (size_t i = 0; i < lstFilesURI.size(); i++)
@@ -326,11 +329,11 @@
 
                 size_t cbBuf = sizeof(DROPFILES) + ((cchFiles + 1) * sizeof(RTUTF16));
-                DROPFILES *pBuf = (DROPFILES *)RTMemAllocZ(cbBuf);
-                if (pBuf)
+                DROPFILES *pDropFiles = (DROPFILES *)RTMemAllocZ(cbBuf);
+                if (pDropFiles)
                 {
-                    pBuf->pFiles = sizeof(DROPFILES);
-                    pBuf->fWide = 1; /* We use unicode. Always. */
-
-                    uint8_t *pCurFile = (uint8_t *)pBuf + pBuf->pFiles;
+                    pDropFiles->pFiles = sizeof(DROPFILES);
+                    pDropFiles->fWide = 1; /* We use unicode. Always. */
+
+                    uint8_t *pCurFile = (uint8_t *)pDropFiles + pDropFiles->pFiles;
                     AssertPtr(pCurFile);
 
@@ -368,8 +371,8 @@
                         if (pMedium->hGlobal)
                         {
-                            LPVOID pMem = GlobalLock(pMedium->hGlobal);
-                            if (pMem)
+                            LPVOID pvMem = GlobalLock(pMedium->hGlobal);
+                            if (pvMem)
                             {
-                                memcpy(pMem, pBuf, cbBuf);
+                                memcpy(pvMem, pDropFiles, cbBuf);
                                 GlobalUnlock(pMedium->hGlobal);
 
@@ -383,16 +386,16 @@
                     }
 
-                    RTMemFree(pBuf);
+                    RTMemFree(pDropFiles);
                 }
             }
             else if (   strMIMEType.startsWith("text/plain")
-                     && va.canConvert(QVariant::String))
+                     && mVaData.canConvert(QVariant::String))
             {
                 bool fUnicode = pFormatEtc->cfFormat == CF_UNICODETEXT;
-                int cbch = fUnicode
+                int cbCh = fUnicode
                          ? sizeof(WCHAR) : sizeof(char);
 
-                QString strText = va.toString();
-                size_t cbSrc = (strText.length() + 1) * cbch;
+                QString strText = mVaData.toString();
+                size_t cbSrc = strText.length() * cbCh;
                 Assert(cbSrc);
                 LPCVOID pvSrc = fUnicode
@@ -400,13 +403,14 @@
                               : (void *)strText.toAscii().constData();
                 AssertPtr(pvSrc);
-#ifdef DEBUG_andy
+
                 LogFlowFunc(("pvSrc=0x%p, cbSrc=%zu, cbch=%d, fUnicode=%RTbool\n",
-                             pvSrc, cbSrc, cbch, fUnicode));
-#endif
+                             pvSrc, cbSrc, cbCh, fUnicode));
+
                 pMedium->tymed = TYMED_HGLOBAL;
                 pMedium->pUnkForRelease = NULL;
                 pMedium->hGlobal = GlobalAlloc(  GMEM_ZEROINIT
                                                | GMEM_MOVEABLE
-                                               | GMEM_DDESHARE, cbSrc);
+                                               | GMEM_DDESHARE,
+                                               cbSrc);
                 if (pMedium->hGlobal)
                 {
@@ -423,5 +427,5 @@
                 }
                 else
-                    hr  = E_OUTOFMEMORY;
+                    hr  = VERR_NO_MEMORY;
             }
             else
@@ -445,5 +449,6 @@
         case TYMED_HGLOBAL:
             pMedium->hGlobal = (HGLOBAL)OleDuplicateData(pThisMedium->hGlobal,
-                                                         pThisFormat->cfFormat, NULL);
+                                                         pThisFormat->cfFormat,
+                                                         0 /* Flags */);
             break;
 
@@ -452,9 +457,9 @@
         }
 
-        pMedium->tymed          = pThisFormat->tymed;
+        pMedium->tymed          = pFormatEtc->tymed;
         pMedium->pUnkForRelease = NULL;
     }
 
-    LogFlowFunc(("hr=%Rhrc\n", hr));
+    LogFlowFunc(("Returning hr=%Rhrc\n", hr));
     return hr;
 }
Index: trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIDnDDataObject_win.h
===================================================================
--- trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIDnDDataObject_win.h	(revision 50560)
+++ trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIDnDDataObject_win.h	(revision 50561)
@@ -25,4 +25,5 @@
 #include <QString>
 #include <QStringList>
+#include <QVariant>
 
 /* Forward declarations: */
@@ -92,5 +93,11 @@
     QStringList mlstFormats;
     QString     mstrFormat;
+    /** The retrieved data as a QVariant. Needed
+     *  for buffering in case a second format needs
+     *  the same data, e.g. CF_TEXT and CF_UNICODETEXT. */
+    QVariant    mVaData;
+    /** The retrieved data as a raw buffer. */
     void       *mpvData;
+    /** Raw buffer size (in bytes). */
     uint32_t    mcbData;
 };
Index: trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIDnDDrag.cpp
===================================================================
--- trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIDnDDrag.cpp	(revision 50560)
+++ trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIDnDDrag.cpp	(revision 50561)
@@ -89,5 +89,6 @@
         HRESULT hr = ::DoDragDrop(pDataObject, pDropSource,
                                   dwOKEffects, &dwEffect);
-        LogFlowThisFunc(("hr=%Rhrc, dwEffect=%RI32\n", hr, dwEffect));
+        LogFlowThisFunc(("DoDragDrop ended with hr=%Rhrc, dwEffect=%RI32\n",
+                         hr, dwEffect));
 
         if (pDropSource)
@@ -150,5 +151,5 @@
     {
         msgCenter().showModalProgressDialog(progress,
-                                            tr("Retrieving metadata ..."), ":/progress_dnd_gh_90px.png",
+                                            tr("Retrieving data ..."), ":/progress_dnd_gh_90px.png",
                                             m_pParent);
         if (!progress.GetCanceled())
@@ -161,6 +162,6 @@
             {
                 /* After the data successfully arrived from the guest, we query it from Main. */
-                QVector<uint8_t> data = guest.DragGHGetData();
-                if (!data.isEmpty())
+                QVector<uint8_t> vecData = guest.DragGHGetData();
+                if (!vecData.isEmpty())
                 {
                     switch (vaType)
@@ -168,5 +169,5 @@
                         case QVariant::String:
                         {
-                            vaData = QVariant(QString(reinterpret_cast<const char*>(data.data())));
+                            vaData = QVariant(QString(reinterpret_cast<const char*>(vecData.constData())));
                             break;
                         }
@@ -174,5 +175,5 @@
                         case QVariant::ByteArray:
                         {
-                            QByteArray ba(reinterpret_cast<const char*>(data.constData()), data.size());
+                            QByteArray ba(reinterpret_cast<const char*>(vecData.constData()), vecData.size());
                             vaData = QVariant(ba);
                             break;
@@ -181,5 +182,5 @@
                         case QVariant::StringList:
                         {
-                            QString strData = QString(reinterpret_cast<const char*>(data.data()));
+                            QString strData = QString(reinterpret_cast<const char*>(vecData.constData()));
                             QStringList lstString = strData.split("\r\n", QString::SkipEmptyParts);
 
Index: trunk/src/VBox/GuestHost/DragAndDrop/DnDURIList.cpp
===================================================================
--- trunk/src/VBox/GuestHost/DragAndDrop/DnDURIList.cpp	(revision 50560)
+++ trunk/src/VBox/GuestHost/DragAndDrop/DnDURIList.cpp	(revision 50561)
@@ -183,7 +183,9 @@
 
                     /* End of file reached or error occurred? */
-                    if (   cbRead < cbToRead
+                    if (   m_cbProcessed == m_cbSize
                         || RT_FAILURE(rc))
+                    {
                         closeInternal();
+                    }
                 }
             }
@@ -572,5 +574,6 @@
 }
 
-RTCString DnDURIList::RootToString(const RTCString &strBasePath /* = "" */)
+RTCString DnDURIList::RootToString(const RTCString &strBasePath /* = "" */,
+                                   const RTCString &strSeparator /* = "\r\n" */)
 {
     RTCString strRet;
@@ -586,7 +589,9 @@
                 if (pszPathURI)
                 {
-                    strRet += RTCString(pszPathURI) + "\r\n";
+                    strRet += RTCString(pszPathURI) + strSeparator;
                     RTStrFree(pszPathURI);
                 }
+                else
+                    break;
                 RTStrFree(pszPath);
             }
@@ -599,5 +604,5 @@
             if (pszPathURI)
             {
-                strRet += RTCString(pszPathURI) + "\r\n";
+                strRet += RTCString(pszPathURI) + strSeparator;
                 RTStrFree(pszPathURI);
             }
Index: trunk/src/VBox/HostServices/DragAndDrop/dndmanager.cpp
===================================================================
--- trunk/src/VBox/HostServices/DragAndDrop/dndmanager.cpp	(revision 50560)
+++ trunk/src/VBox/HostServices/DragAndDrop/dndmanager.cpp	(revision 50561)
@@ -41,5 +41,6 @@
 
 /**
- * Internal DnD message class for informing the guest about a new directory.
+ * Internal DnD message class for informing the
+ * guest about a new directory.
  *
  * @see DnDHGSendDataMessage
@@ -55,11 +56,16 @@
         , m_pvProgressUser(pvProgressUser)
     {
+        RTCString strPath = m_URIObject.GetDestPath();
+        LogFlowFunc(("strPath=%s (%zu)\n", strPath.c_str(), strPath.length()));
+
         VBOXHGCMSVCPARM paTmpParms[3];
-        paTmpParms[0].setString(m_URIObject.GetDestPath().c_str());
-        paTmpParms[1].setUInt32((uint32_t)(m_URIObject.GetDestPath().length() + 1));
+        paTmpParms[0].setString(strPath.c_str());
+        paTmpParms[1].setUInt32((uint32_t)(strPath.length() + 1));
         paTmpParms[2].setUInt32(m_URIObject.GetMode());
 
         m_pNextMsg = new HGCM::Message(DragAndDropSvc::HOST_DND_HG_SND_DIR, 3, paTmpParms);
     }
+
+public:
 
     int currentMessage(uint32_t uMsg, uint32_t cParms, VBOXHGCMSVCPARM paParms[])
@@ -78,5 +84,5 @@
     DnDURIObject           m_URIObject;
 
-    /* Progress stuff */
+    /* Progress stuff. */
     PFNDNDPRIVATEPROGRESS  m_pfnProgressCallback;
     void                  *m_pvProgressUser;
@@ -96,4 +102,6 @@
     virtual ~DnDHGSendFilePrivate(void);
 
+public:
+
     int currentMessage(uint32_t uMsg, uint32_t cParms, VBOXHGCMSVCPARM paParms[]);
 
@@ -101,7 +109,9 @@
 
     DnDURIObject           m_URIObject;
-    VBOXHGCMSVCPARM        m_paSkelParms[5];
-
-    /* Progress stuff */
+    /** Skeleton parameters for the next upcoming message in case
+     *  the file data didn't fit completely into the first one. */
+    VBOXHGCMSVCPARM        m_aSkelParms[5];
+
+    /* Progress stuff. */
     PFNDNDPRIVATEPROGRESS  m_pfnProgressCallback;
     void                  *m_pvProgressUser;
@@ -127,5 +137,5 @@
     size_t                 m_cbDone;
 
-    /* Progress stuff */
+    /* Progress stuff. */
     PFNDNDPRIVATEPROGRESS  m_pfnProgressCallback;
     void                  *m_pvProgressUser;
@@ -146,11 +156,14 @@
     , m_pvProgressUser(pvProgressUser)
 {
-    m_paSkelParms[0].setString(m_URIObject.GetDestPath().c_str());
-    m_paSkelParms[1].setUInt32((uint32_t)(m_URIObject.GetDestPath().length() + 1));
-    m_paSkelParms[2].setPointer(NULL, 0);
-    m_paSkelParms[3].setUInt32(0);
-    m_paSkelParms[4].setUInt32(m_URIObject.GetMode());
-
-    m_pNextMsg = new HGCM::Message(DragAndDropSvc::HOST_DND_HG_SND_FILE, 5, m_paSkelParms);
+    LogFlowFunc(("strPath=%s (%zu)\n",
+                 m_URIObject.GetDestPath().c_str(), m_URIObject.GetDestPath().length()));
+
+    m_aSkelParms[0].setString(m_URIObject.GetDestPath().c_str()); /* pvName */
+    m_aSkelParms[1].setUInt32((uint32_t)(m_URIObject.GetDestPath().length() + 1)); /* cbName */
+    m_aSkelParms[2].setPointer(NULL, 0); /* pvData */
+    m_aSkelParms[3].setUInt32(0); /* cbData */
+    m_aSkelParms[4].setUInt32(m_URIObject.GetMode()); /* fMode */
+
+    m_pNextMsg = new HGCM::Message(DragAndDropSvc::HOST_DND_HG_SND_FILE, 5, m_aSkelParms);
 }
 
@@ -174,14 +187,17 @@
     {
         /* Get buffer size + pointer to buffer from guest side. */
-        uint32_t cbToRead = paParms[2].u.pointer.size;
+        uint32_t cbToRead = paParms[2].u.pointer.size; /* cbData */
         Assert(cbToRead);
-        void *pvBuf = paParms[2].u.pointer.addr;
+        void *pvBuf = paParms[2].u.pointer.addr; /* pvData */
         AssertPtr(pvBuf);
 
         rc = m_URIObject.Read(pvBuf, cbToRead, &cbRead);
+        LogFlowFunc(("Read %RU32 bytes (%RU32 bytes buffer) for \"%s\", rc=%Rrc\n",
+                     cbRead, cbToRead, m_URIObject.GetDestPath().c_str(), rc));
+
         if (RT_LIKELY(RT_SUCCESS(rc)))
         {
-            /* Tell the guest the actual size. */
-            paParms[3].setUInt32((uint32_t)cbRead);
+            /* Tell the guest the actual size read. */
+            paParms[3].setUInt32((uint32_t)cbRead); /* cbData */
         }
     }
@@ -195,5 +211,5 @@
                 /* More data needed to send over. Prepare the next message. */
                 m_pNextMsg = new HGCM::Message(DragAndDropSvc::HOST_DND_HG_SND_FILE, 5 /* cParms */,
-                                               m_paSkelParms);
+                                               m_aSkelParms);
             }
             catch(std::bad_alloc &)
@@ -323,5 +339,5 @@
         Assert(cbList);
 
-        LogFlowFunc(("Old data: '%s'\n", pszList));
+        LogFlowFunc(("Old data (%RU32 bytes): '%s'\n", cbList, pszList));
 
         /* The list is separated by newline (even if only one file is listed). */
@@ -330,5 +346,5 @@
         if (!lstURIOrg.isEmpty())
         {
-            rc = m_lstURI.AppendNativePathsFromList(lstURIOrg, 0 /* fFlags */);
+            rc = m_lstURI.AppendURIPathsFromList(lstURIOrg, 0 /* fFlags */);
             if (RT_SUCCESS(rc))
             {
@@ -351,5 +367,7 @@
                 paParms[4].u.uint32       = (uint32_t)(strNewURIs.length() + 1);
 
-                LogFlowFunc(("Set new data: '%s'\n", (char*)paParms[3].u.pointer.addr));
+                LogFlowFunc(("Set new data (%RU32 bytes): '%s'\n",
+                            paParms[3].u.pointer.size,
+                            (const char*)paParms[3].u.pointer.addr));
             }
         }
Index: trunk/src/VBox/HostServices/DragAndDrop/service.cpp
===================================================================
--- trunk/src/VBox/HostServices/DragAndDrop/service.cpp	(revision 50560)
+++ trunk/src/VBox/HostServices/DragAndDrop/service.cpp	(revision 50561)
@@ -72,8 +72,9 @@
 {
 public:
+
     explicit DragAndDropService(PVBOXHGCMSVCHELPERS pHelpers)
-      : HGCM::AbstractService<DragAndDropService>(pHelpers)
-      , m_pManager(0)
-      , m_cClients(0)
+        : HGCM::AbstractService<DragAndDropService>(pHelpers)
+        , m_pManager(0)
+        , m_cClients(0)
     {}
 
@@ -88,6 +89,5 @@
 
     static DECLCALLBACK(int) progressCallback(uint32_t uPercentage, uint32_t uState, int rc, void *pvUser);
-    int      hostMessage(uint32_t u32Function, uint32_t cParms, VBOXHGCMSVCPARM paParms[]);
-    void     modeSet(uint32_t u32Mode);
+    int modeSet(uint32_t u32Mode);
     inline uint32_t modeGet() { return m_u32Mode; };
 
@@ -110,4 +110,6 @@
     pTable->pfnLoadState         = NULL;  /* construction done before restoring suffices */
     pTable->pfnRegisterExtension = svcRegisterExtension;
+
+    /* Drag'n drop mode is disabled by default. */
     modeSet(VBOX_DRAG_AND_DROP_MODE_OFF);
 
@@ -117,5 +119,5 @@
 }
 
-int DragAndDropService::uninit()
+int DragAndDropService::uninit(void)
 {
     delete m_pManager;
@@ -131,4 +133,12 @@
     else
         AssertMsgFailed(("Maximum number of clients reached\n"));
+
+    /*
+     * Clear the message queue as soon as a new clients connect
+     * to ensure that every client has the same state.
+     */
+    if (m_pManager)
+        m_pManager->clear();
+
     return VINF_SUCCESS;
 }
@@ -136,5 +146,5 @@
 int DragAndDropService::clientDisconnect(uint32_t u32ClientID, void *pvClient)
 {
-    /* Remove all waiters with this clientId. */
+    /* Remove all waiters with this u32ClientID. */
     for (size_t i = 0; i < m_clientQueue.size(); )
     {
@@ -142,5 +152,7 @@
         if (pClient->clientId() == u32ClientID)
         {
-            m_pHelpers->pfnCallComplete(pClient->handle(), VERR_INTERRUPTED);
+            if (m_pHelpers)
+                m_pHelpers->pfnCallComplete(pClient->handle(), VERR_INTERRUPTED);
+
             m_clientQueue.removeAt(i);
             delete pClient;
@@ -153,6 +165,7 @@
 }
 
-void DragAndDropService::modeSet(uint32_t u32Mode)
-{
+int DragAndDropService::modeSet(uint32_t u32Mode)
+{
+    /** @todo Validate mode. */
     switch (u32Mode)
     {
@@ -166,5 +179,8 @@
         default:
             m_u32Mode = VBOX_DRAG_AND_DROP_MODE_OFF;
-    }
+            break;
+    }
+
+    return VINF_SUCCESS;
 }
 
@@ -222,5 +238,4 @@
     if (!fIgnoreRequest)
     {
-        rc = VINF_SUCCESS;
         switch (u32Function)
         {
@@ -244,5 +259,6 @@
                         && paParms[2].u.uint32) /* Blocking? */
                     {
-                        m_clientQueue.append(new HGCM::Client(u32ClientID, callHandle, u32Function, cParms, paParms));
+                        m_clientQueue.append(new HGCM::Client(u32ClientID, callHandle,
+                                                              u32Function, cParms, paParms));
                         rc = VINF_HGCM_ASYNC_EXECUTE;
                     }
@@ -393,7 +409,9 @@
                     DragAndDropSvc::VBOXDNDCBEVTERRORDATA data;
                     data.hdr.u32Magic = DragAndDropSvc::CB_MAGIC_DND_GH_EVT_ERROR;
+
                     uint32_t rcOp;
                     paParms[0].getUInt32(&rcOp);
                     data.rc = rcOp;
+
                     if (m_pfnHostCallback)
                         rc = m_pfnHostCallback(m_pvHostData, u32Function, &data, sizeof(data));
@@ -411,74 +429,24 @@
     }
     else
-        rc = VERR_NOT_SUPPORTED;
+        rc = VERR_ACCESS_DENIED;
 
     /* If async execute is requested, we didn't notify the guest about
      * completion. The client is queued into the waiters list and will be
      * notified as soon as a new event is available. */
-    if (rc != VINF_HGCM_ASYNC_EXECUTE)
+    if (   rc != VINF_HGCM_ASYNC_EXECUTE
+        && m_pHelpers)
+    {
         m_pHelpers->pfnCallComplete(callHandle, rc);
+    }
+
     LogFlowFunc(("Returning rc=%Rrc\n", rc));
 }
 
-int DragAndDropService::hostMessage(uint32_t u32Function, uint32_t cParms, VBOXHGCMSVCPARM paParms[])
-{
-    int rc = VINF_SUCCESS;
-#if 0
-    HGCM::Message *pMessage = new HGCM::Message(u32Function, cParms, paParms);
-    m_hostQueue.push(pMessage);
-//    bool fPush = true;
-    RTPrintf("client queue %u\n", m_clientQueue.size());
-    RTPrintf("host   queue %u\n", m_hostQueue.size());
-    if (!m_clientQueue.empty())
-    {
-        pMessage = m_hostQueue.front();
-        HGCM::Client *pClient = m_clientQueue.front();
-        /* Check if this was a request for getting the next host
-         * message. If so, return the message id and the parameter
-         * count. The message itself has to be queued. */
-        if (pClient->message() == DragAndDropSvc::GUEST_GET_NEXT_HOST_MSG)
-        {
-            RTPrintf("client is waiting for next host msg\n");
-//            rc = VERR_TOO_MUCH_DATA;
-            pClient->addMessageInfo(pMessage);
-            /* temp */
-//        m_pHelpers->pfnCallComplete(pClient->handle(), rc);
-//        m_clientQueue.pop();
-//        delete pClient;
-        }
-        else
-        {
-            RTPrintf("client is waiting for host msg (%d)\n", u32Function);
-            /* There is a request for a host message pending. Check
-             * if this is the correct message and if so deliver. If
-             * not the message will be queued. */
-            rc = pClient->addMessage(pMessage);
-            m_hostQueue.pop();
-            delete pMessage;
-//            if (RT_SUCCESS(rc))
-//                fPush = false;
-        }
-        /* In any case mark this client request as done. */
-        m_pHelpers->pfnCallComplete(pClient->handle(), rc);
-        m_clientQueue.pop_front();
-        delete pClient;
-    }
-//    if (fPush)
-//    {
-//        RTPrintf("push message\n");
-//        m_hostQueue.push(pMessage);
-//    }
-//    else
-//        delete pMessage;
-#endif
-
-    return rc;
-}
-
-int DragAndDropService::hostCall(uint32_t u32Function, uint32_t cParms, VBOXHGCMSVCPARM paParms[])
+int DragAndDropService::hostCall(uint32_t u32Function,
+                                 uint32_t cParms, VBOXHGCMSVCPARM paParms[])
 {
     LogFlowFunc(("u32Function=%RU32, cParms=%RU32\n", u32Function, cParms));
 
-    int rc = VINF_SUCCESS;
+    int rc;
     if (u32Function == DragAndDropSvc::HOST_DND_SET_MODE)
     {
@@ -488,39 +456,59 @@
             rc = VERR_INVALID_PARAMETER;
         else
-            modeSet(paParms[0].u.uint32);
+            rc = modeSet(paParms[0].u.uint32);
     }
     else if (modeGet() != VBOX_DRAG_AND_DROP_MODE_OFF)
     {
-        rc = m_pManager->addMessage(u32Function, cParms, paParms);
-        if (   RT_SUCCESS(rc)
-            && !m_clientQueue.isEmpty())
+        if (!m_clientQueue.isEmpty()) /* At least one client on the guest connected? */
         {
-            HGCM::Client *pClient = m_clientQueue.first();
-            AssertPtr(pClient);
-            /* Check if this was a request for getting the next host
-             * message. If so, return the message id and the parameter
-             * count. The message itself has to be queued. */
-            if (pClient->message() == DragAndDropSvc::GUEST_DND_GET_NEXT_HOST_MSG)
-            {
-                LogFlowFunc(("Client %RU32 is waiting for next host msg\n", pClient->clientId()));
-
-                uint32_t uMsg1;
-                uint32_t cParms1;
-                rc = m_pManager->nextMessageInfo(&uMsg1, &cParms1);
-                if (RT_SUCCESS(rc))
-                {
-                    pClient->addMessageInfo(uMsg1, cParms1);
-                    m_pHelpers->pfnCallComplete(pClient->handle(), rc);
-                    m_clientQueue.removeFirst();
-                    delete pClient;
-                }
-                else
-                    AssertMsgFailed(("Should not happen!"));
+            rc = m_pManager->addMessage(u32Function, cParms, paParms);
+            if (RT_SUCCESS(rc))
+            {
+                HGCM::Client *pClient = m_clientQueue.first();
+                AssertPtr(pClient);
+
+                /* Check if this was a request for getting the next host
+                 * message. If so, return the message id and the parameter
+                 * count. The message itself has to be queued. */
+                uint32_t uMsg = pClient->message();
+                if (uMsg == DragAndDropSvc::GUEST_DND_GET_NEXT_HOST_MSG)
+                {
+                    LogFlowFunc(("Client %RU32 is waiting for next host msg\n", pClient->clientId()));
+
+                    uint32_t uMsg1;
+                    uint32_t cParms1;
+                    rc = m_pManager->nextMessageInfo(&uMsg1, &cParms1);
+                    if (RT_SUCCESS(rc))
+                    {
+                        pClient->addMessageInfo(uMsg1, cParms1);
+                        if (m_pHelpers)
+                            m_pHelpers->pfnCallComplete(pClient->handle(), rc);
+
+                        m_clientQueue.removeFirst();
+                        delete pClient;
+                    }
+                    else
+                        AssertMsgFailed(("m_pManager::nextMessageInfo failed with rc=%Rrc\n", rc));
+                }
+                else
+                    AssertMsgFailed(("Client ID=%RU32 in wrong state with uMsg=%RU32\n",
+                                     pClient->clientId(), uMsg));
             }
             else
-                AssertMsgFailed(("Should not happen!"));
+                AssertMsgFailed(("Adding new message of type=%RU32 failed with rc=%Rrc\n",
+                                 u32Function, rc));
         }
-//      else
-//          AssertMsgFailed(("Should not happen %Rrc!", rc));
+        else
+        {
+            /* Tell the host that the guest does not support drag'n drop.
+             * This might happen due to not installed Guest Additions or
+             * not running VBoxTray/VBoxClient. */
+            rc = VERR_NOT_SUPPORTED;
+        }
+    }
+    else
+    {
+        /* Tell the host that a wrong drag'n drop mode is set. */
+        rc = VERR_ACCESS_DENIED;
     }
 
@@ -534,4 +522,5 @@
 
     DragAndDropService *pSelf = static_cast<DragAndDropService *>(pvUser);
+    AssertPtr(pSelf);
 
     if (pSelf->m_pfnHostCallback)
@@ -545,5 +534,7 @@
         data.rc           = rc;
 
-        return pSelf->m_pfnHostCallback(pSelf->m_pvHostData, DragAndDropSvc::GUEST_DND_HG_EVT_PROGRESS, &data, sizeof(data));
+        return pSelf->m_pfnHostCallback(pSelf->m_pvHostData,
+                                        DragAndDropSvc::GUEST_DND_HG_EVT_PROGRESS,
+                                        &data, sizeof(data));
     }
 
Index: trunk/src/VBox/Main/src-client/GuestDnDImpl.cpp
===================================================================
--- trunk/src/VBox/Main/src-client/GuestDnDImpl.cpp	(revision 50560)
+++ trunk/src/VBox/Main/src-client/GuestDnDImpl.cpp	(revision 50561)
@@ -239,6 +239,6 @@
     DnDGuestResponse *response(void) const { return m_pDnDResponse; }
 
-    void adjustCoords(ULONG uScreenId, ULONG *puX, ULONG *puY) const;
-    void hostCall(uint32_t u32Function, uint32_t cParms, PVBOXHGCMSVCPARM paParms) const;
+    HRESULT adjustCoords(ULONG uScreenId, ULONG *puX, ULONG *puY) const;
+    int hostCall(uint32_t u32Function, uint32_t cParms, PVBOXHGCMSVCPARM paParms) const;
 
     /* Static helpers. */
@@ -310,9 +310,9 @@
 int DnDGuestResponse::waitForGuestResponse(RTMSINTERVAL msTimeout /*= 500 */)
 {
-    int vrc = RTSemEventWait(m_EventSem, msTimeout);
+    int rc = RTSemEventWait(m_EventSem, msTimeout);
 #ifdef DEBUG_andy
-    LogFlowFunc(("msTimeout=%RU32, rc=%Rrc\n", msTimeout, vrc));
+    LogFlowFunc(("msTimeout=%RU32, rc=%Rrc\n", msTimeout, rc));
 #endif
-    return vrc;
+    return rc;
 }
 
@@ -350,6 +350,8 @@
         m_pvData = NULL;
     }
-
     m_cbData = 0;
+
+    m_cbDataCurrent = 0;
+    m_cbDataTotal = 0;
 }
 
@@ -377,46 +379,47 @@
     {
         BOOL fCompleted;
-        HRESULT rc = m_progress->COMGETTER(Completed)(&fCompleted);
+        HRESULT hr = m_progress->COMGETTER(Completed)(&fCompleted);
         if (!fCompleted)
         {
             if (uState == DragAndDropSvc::DND_PROGRESS_ERROR)
             {
-                rc = m_progress->notifyComplete(E_FAIL,
+                hr = m_progress->notifyComplete(E_FAIL,
                                                 COM_IIDOF(IGuest),
                                                 m_parent->getComponentName(),
                                                 m_parent->tr("Drag'n drop guest error (%Rrc)"), rcOp);
+                reset();
             }
             else if (uState == DragAndDropSvc::DND_PROGRESS_CANCELLED)
             {
-                rc = m_progress->Cancel();
-                vrc = VERR_CANCELLED;
+                hr = m_progress->Cancel();
+                if (SUCCEEDED(hr))
+                    vrc = VERR_CANCELLED;
+
+                reset();
             }
             else /* uState == DragAndDropSvc::DND_PROGRESS_RUNNING */
             {
-                rc = m_progress->SetCurrentOperationProgress(uPercentage);
-#ifndef DEBUG_andy
-                Assert(SUCCEEDED(rc));
-#endif
+                hr = m_progress->SetCurrentOperationProgress(uPercentage);
+                AssertComRC(hr);
                 if (   uState      == DragAndDropSvc::DND_PROGRESS_COMPLETE
                     || uPercentage >= 100)
-                    rc = m_progress->notifyComplete(S_OK);
+                    hr = m_progress->notifyComplete(S_OK);
             }
+        }
+    }
+
+    return vrc;
+}
+
+int DnDGuestResponse::dataSetStatus(size_t cbDataAdd, size_t cbDataTotal /* = 0 */)
+{
+    if (cbDataTotal)
+    {
 #ifndef DEBUG_andy
-            Assert(SUCCEEDED(rc));
+        AssertMsg(m_cbDataTotal <= cbDataTotal, ("New data size must not be smaller (%zu) than old value (%zu)\n",
+                                                 cbDataTotal, m_cbDataTotal));
 #endif
-        }
-    }
-
-    return vrc;
-}
-
-int DnDGuestResponse::dataSetStatus(size_t cbDataAdd, size_t cbDataTotal /* = 0 */)
-{
-    if (cbDataTotal)
-    {
-        AssertMsg(m_cbDataTotal <= cbDataTotal, ("New data size size must not be smaller (%zu) than old value (%zu)\n",
-                                                 cbDataTotal, m_cbDataTotal));
+        LogFlowFunc(("Updating total data size from %zu to %zu\n", m_cbDataTotal, cbDataTotal));
         m_cbDataTotal = cbDataTotal;
-        LogFlowFunc(("Updating total data size to: %zu\n", m_cbDataTotal));
     }
     AssertMsg(m_cbDataTotal, ("m_cbDataTotal must not be <= 0\n"));
@@ -433,10 +436,9 @@
     LogFlowFunc(("Updating transfer status (%zu/%zu), status=%ld\n",
                  m_cbDataCurrent, m_cbDataTotal, uStatus));
-#endif
-
+#else
     AssertMsg(m_cbDataCurrent <= m_cbDataTotal,
               ("More data transferred (%RU32) than initially announced (%RU32)\n",
               m_cbDataCurrent, m_cbDataTotal));
-
+#endif
     int rc = setProgress(cPercentage, uStatus);
 
@@ -455,27 +457,30 @@
 }
 
-void GuestDnDPrivate::adjustCoords(ULONG uScreenId, ULONG *puX, ULONG *puY) const
+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 rc = p->mParent->COMGETTER(Display)(pDisplay.asOutParam());
-    if (FAILED(rc))
-        throw rc;
+    HRESULT hr = p->mParent->COMGETTER(Display)(pDisplay.asOutParam());
+    if (FAILED(hr))
+        return hr;
 
     ComPtr<IFramebuffer> pFramebuffer;
     LONG xShift, yShift;
-    rc = pDisplay->GetFramebuffer(uScreenId, pFramebuffer.asOutParam(),
+    hr = pDisplay->GetFramebuffer(uScreenId, pFramebuffer.asOutParam(),
                                   &xShift, &yShift);
-    if (FAILED(rc))
-        throw rc;
+    if (FAILED(hr))
+        return hr;
 
     *puX += xShift;
     *puY += yShift;
-}
-
-void GuestDnDPrivate::hostCall(uint32_t u32Function, uint32_t cParms, PVBOXHGCMSVCPARM paParms) const
-{
-    VMMDev *vmmDev = NULL;
+
+    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.
@@ -486,21 +491,23 @@
         /* Forward the information to the VMM device. */
         AssertPtr(p->mParent);
-        vmmDev = p->mParent->getVMMDev();
-    }
-
-    if (!vmmDev)
+        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 msg=%RU32, numParms=%RU32\n", u32Function, cParms));
-    int vrc = vmmDev->hgcmHostCall("VBoxDragAndDropSvc",
+    int rc = pVMMDev->hgcmHostCall("VBoxDragAndDropSvc",
                                    u32Function,
                                    cParms, paParms);
-    if (RT_FAILURE(vrc))
-    {
-        LogFlowFunc(("hgcmHostCall error: %Rrc\n", vrc));
+    if (RT_FAILURE(rc))
+    {
+        LogFlowFunc(("hgcmHostCall error: %Rrc\n", rc));
         throw p->setError(VBOX_E_VM_ERROR,
-                          p->tr("hgcmHostCall failed (%Rrc)"), vrc);
-    }
+                          p->tr("hgcmHostCall failed (%Rrc)"), rc);
+    }
+
+    return rc;
 }
 
@@ -653,5 +660,5 @@
         return S_OK;
 
-    HRESULT rc = S_OK;
+    HRESULT hr = S_OK;
 
     try
@@ -674,19 +681,19 @@
                     paParms);
 
-        DnDGuestResponse *pDnD = d->response();
+        DnDGuestResponse *pResp = d->response();
         /* This blocks until the request is answered (or timeout). */
-        if (pDnD->waitForGuestResponse() == VERR_TIMEOUT)
+        if (pResp->waitForGuestResponse() == VERR_TIMEOUT)
             return S_OK;
 
         /* Copy the response info */
-        *pResultAction = d->toMainAction(pDnD->defAction());
+        *pResultAction = d->toMainAction(pResp->defAction());
         LogFlowFunc(("*pResultAction=%ld\n", *pResultAction));
     }
-    catch (HRESULT rc2)
-    {
-        rc = rc2;
-    }
-
-    return rc;
+    catch (HRESULT hr2)
+    {
+        hr = hr2;
+    }
+
+    return hr;
 }
 
@@ -717,5 +724,5 @@
         return S_OK;
 
-    HRESULT rc = S_OK;
+    HRESULT hr = S_OK;
 
     try
@@ -738,19 +745,19 @@
                     paParms);
 
-        DnDGuestResponse *pDnD = d->response();
+        DnDGuestResponse *pResp = d->response();
         /* This blocks until the request is answered (or timeout). */
-        if (pDnD->waitForGuestResponse() == VERR_TIMEOUT)
+        if (pResp->waitForGuestResponse() == VERR_TIMEOUT)
             return S_OK;
 
         /* Copy the response info */
-        *pResultAction = d->toMainAction(pDnD->defAction());
+        *pResultAction = d->toMainAction(pResp->defAction());
         LogFlowFunc(("*pResultAction=%ld\n", *pResultAction));
     }
-    catch (HRESULT rc2)
-    {
-        rc = rc2;
-    }
-
-    return rc;
+    catch (HRESULT hr2)
+    {
+        hr = hr2;
+    }
+
+    return hr;
 }
 
@@ -760,5 +767,5 @@
     const ComObjPtr<Guest> &p = d->p;
 
-    HRESULT rc = S_OK;
+    HRESULT hr = S_OK;
 
     try
@@ -768,14 +775,14 @@
                     NULL);
 
-        DnDGuestResponse *pDnD = d->response();
+        DnDGuestResponse *pResp = d->response();
         /* This blocks until the request is answered (or timeout). */
-        pDnD->waitForGuestResponse();
-    }
-    catch (HRESULT rc2)
-    {
-        rc = rc2;
-    }
-
-    return rc;
+        pResp->waitForGuestResponse();
+    }
+    catch (HRESULT hr2)
+    {
+        hr = hr2;
+    }
+
+    return hr;
 }
 
@@ -807,5 +814,5 @@
         return S_OK;
 
-    HRESULT rc = S_OK;
+    HRESULT hr = S_OK;
 
     try
@@ -828,21 +835,21 @@
                     paParms);
 
-        DnDGuestResponse *pDnD = d->response();
+        DnDGuestResponse *pResp = d->response();
         /* This blocks until the request is answered (or timeout). */
-        if (pDnD->waitForGuestResponse() == VERR_TIMEOUT)
+        if (pResp->waitForGuestResponse() == VERR_TIMEOUT)
             return S_OK;
 
         /* Copy the response info */
-        *pResultAction = d->toMainAction(pDnD->defAction());
-        Bstr(pDnD->format()).cloneTo(pstrFormat);
+        *pResultAction = d->toMainAction(pResp->defAction());
+        Bstr(pResp->format()).cloneTo(pstrFormat);
 
         LogFlowFunc(("*pResultAction=%ld\n", *pResultAction));
     }
-    catch (HRESULT rc2)
-    {
-        rc = rc2;
-    }
-
-    return rc;
+    catch (HRESULT hr2)
+    {
+        hr = hr2;
+    }
+
+    return hr;
 }
 
@@ -853,5 +860,5 @@
     const ComObjPtr<Guest> &p = d->p;
 
-    HRESULT rc = S_OK;
+    HRESULT hr = S_OK;
 
     try
@@ -868,7 +875,7 @@
         paParms[i++].setUInt32((uint32_t)sfaData.size());
 
-        DnDGuestResponse *pDnD = d->response();
+        DnDGuestResponse *pResp = d->response();
         /* Reset any old progress status. */
-        pDnD->resetProgress(p);
+        pResp->resetProgress(p);
 
         /* Note: The actual data transfer of files/directoies is performed by the
@@ -879,12 +886,12 @@
 
         /* Query the progress object to the caller. */
-        pDnD->queryProgressTo(ppProgress);
-    }
-    catch (HRESULT rc2)
-    {
-        rc = rc2;
-    }
-
-    return rc;
+        pResp->queryProgressTo(ppProgress);
+    }
+    catch (HRESULT hr2)
+    {
+        hr = hr2;
+    }
+
+    return hr;
 }
 
@@ -901,5 +908,5 @@
     *pDefaultAction = DragAndDropAction_Ignore;
 
-    HRESULT rc = S_OK;
+    HRESULT hr = S_OK;
 
     try
@@ -913,27 +920,25 @@
                     paParms);
 
-        DnDGuestResponse *pDnD = d->response();
-        /* This blocks until the request is answered (or timeout). */
-        if (pDnD->waitForGuestResponse() == VERR_TIMEOUT)
+        /* This blocks until the request is answered (or timed out). */
+        DnDGuestResponse *pResp = d->response();
+        if (pResp->waitForGuestResponse() == VERR_TIMEOUT)
             return S_OK;
 
-        if (isDnDIgnoreAction(pDnD->defAction()))
+        if (isDnDIgnoreAction(pResp->defAction()))
             return S_OK;
 
         /* Fetch the default action to use. */
-        *pDefaultAction = d->toMainAction(pDnD->defAction());
-        /* Convert the formats strings to a vector of strings. */
-        d->toFormatSafeArray(pDnD->format(), ComSafeArrayOutArg(formats));
-        /* Convert the action bit field to a vector of actions. */
-        d->toMainActions(pDnD->allActions(), ComSafeArrayOutArg(allowedActions));
+        *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 rc2)
-    {
-        rc = rc2;
-    }
-
-    return rc;
+    catch (HRESULT hr2)
+    {
+        hr = hr2;
+    }
+
+    return hr;
 }
 
@@ -957,6 +962,8 @@
                  pcszFormat, uAction, fNeedsDropDir));
 
-    DnDGuestResponse *pDnD = d->response();
-    AssertPtr(pDnD);
+    DnDGuestResponse *pResp = d->response();
+    AssertPtr(pResp);
+
+    pResp->reset();
 
     if (fNeedsDropDir)
@@ -970,5 +977,5 @@
         LogFlowFunc(("Dropped files directory on the host is: %s\n", szDropDir));
 
-        pDnD->setDropDir(szDropDir);
+        pResp->setDropDir(szDropDir);
     }
 
@@ -982,6 +989,6 @@
 
         /* Reset any old data and the progress status. */
-        pDnD->reset();
-        pDnD->resetProgress(p);
+        pResp->reset();
+        pResp->resetProgress(p);
 
         d->hostCall(DragAndDropSvc::HOST_DND_GH_EVT_DROPPED,
@@ -990,9 +997,9 @@
 
         /* Query the progress object to the caller. */
-        pDnD->queryProgressTo(ppProgress);
-    }
-    catch (HRESULT rc2)
-    {
-        hr = rc2;
+        pResp->queryProgressTo(ppProgress);
+    }
+    catch (HRESULT hr2)
+    {
+        hr = hr2;
     }
 
@@ -1019,9 +1026,11 @@
 
             Utf8Str strFormat = pResp->format();
-            LogFlowFunc(("strFormat=%s, strDropDir=%s\n",
-                         strFormat.c_str(), pResp->dropDir().c_str()));
+            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 */);
@@ -1029,6 +1038,7 @@
                 {
                     Utf8Str strURIs = lstURI.RootToString(pResp->dropDir());
-                    if (sfaData.resize(strURIs.length()))
-                        memcpy(sfaData.raw(), strURIs.c_str(), strURIs.length());
+                    size_t cbURIs = strURIs.length();
+                    if (sfaData.resize(cbURIs + 1 /* Include termination */))
+                        memcpy(sfaData.raw(), strURIs.c_str(), cbURIs);
                     else
                         hr = E_OUTOFMEMORY;
@@ -1049,6 +1059,4 @@
         }
 
-        LogFlowFunc(("cbData=%zu\n", cbData));
-
         /* Detach in any case, regardless of data size. */
         sfaData.detachTo(ComSafeArrayOutArg(data));
