Index: /trunk/include/VBox/GuestHost/DragAndDrop.h
===================================================================
--- /trunk/include/VBox/GuestHost/DragAndDrop.h	(revision 55555)
+++ /trunk/include/VBox/GuestHost/DragAndDrop.h	(revision 55556)
@@ -77,5 +77,5 @@
     const RTCString &GetSourcePath(void) const { return m_strSrcPath; }
     const RTCString &GetDestPath(void) const { return m_strTgtPath; }
-    uint64_t GetMode(void) const { return m_fMode; }
+    uint32_t GetMode(void) const { return m_fCreationMode; }
     uint64_t GetProcessed(void) const { return m_cbProcessed; }
     uint64_t GetSize(void) const { return m_cbSize; }
@@ -110,6 +110,6 @@
     RTCString m_strSrcPath;
     RTCString m_strTgtPath;
-    /** File mode. */
-    uint32_t  m_fMode;
+    /** File creation mode. */
+    uint32_t  m_fCreationMode;
     /** Size (in bytes) to read/write. */
     uint64_t  m_cbSize;
Index: /trunk/src/VBox/Additions/common/VBoxGuestLib/VBoxGuestR3LibDragAndDrop.cpp
===================================================================
--- /trunk/src/VBox/Additions/common/VBoxGuestLib/VBoxGuestR3LibDragAndDrop.cpp	(revision 55555)
+++ /trunk/src/VBox/Additions/common/VBoxGuestLib/VBoxGuestR3LibDragAndDrop.cpp	(revision 55556)
@@ -1318,10 +1318,9 @@
 
     uint32_t cbBuf = _64K; /** @todo Make this configurable? */
-    void *pvBuf = RTMemAlloc(cbBuf);
+    void *pvBuf = RTMemAlloc(cbBuf); /** @todo Make this buffer part of PVBGLR3GUESTDNDCMDCTX? */
     if (!pvBuf)
         return VERR_NO_MEMORY;
 
     RTCString strPath = obj.GetDestPath();
-    LogFlowFunc(("strFile=%s (%zu), fMode=0x%x\n", strPath.c_str(), strPath.length(), obj.GetMode()));
 
     int rc = obj.Open(DnDURIObject::Source, RTFILE_O_OPEN | RTFILE_O_READ | RTFILE_O_DENY_WRITE);
@@ -1332,5 +1331,6 @@
     }
 
-    LogFlowFunc(("cbSize=%RU64, uProtocol=%RU32, uClientID=%RU32\n", obj.GetSize(), pCtx->uProtocol, pCtx->uClientID));
+    LogFlowFunc(("strFile=%s (%zu), cbSize=%RU64, fMode=0x%x\n", strPath.c_str(), strPath.length(), obj.GetSize(), obj.GetMode()));
+    LogFlowFunc(("uProtocol=%RU32, uClientID=%RU32\n", pCtx->uProtocol, pCtx->uClientID));
 
     if (pCtx->uProtocol >= 2) /* Protocol version 2 and up sends a file header first. */
@@ -1431,4 +1431,6 @@
     }
 
+    obj.Close();
+
     RTMemFree(pvBuf);
 
Index: /trunk/src/VBox/GuestHost/DragAndDrop/DnDURIList.cpp
===================================================================
--- /trunk/src/VBox/GuestHost/DragAndDrop/DnDURIList.cpp	(revision 55555)
+++ /trunk/src/VBox/GuestHost/DragAndDrop/DnDURIList.cpp	(revision 55556)
@@ -82,14 +82,15 @@
     m_cbTotal += cbSize;
 #ifdef DEBUG_andy
-    LogFlowFunc(("strSrcPath=%s, strDstPath=%s, fMode=0x%x, cbSize=%RU64, cbTotal=%zu\n",
-                 pcszPath, &pcszPath[cbBaseLen], objInfo.Attr.fMode, cbSize, m_cbTotal));
-#endif
-
-    PRTDIR hDir;
+    LogFlowFunc(("strSrcPath=%s, strDstPath=%s, fMode=0x%x, cbSize=%RU64, cTotal=%RU32, cbTotal=%zu\n",
+                 pcszPath, &pcszPath[cbBaseLen], objInfo.Attr.fMode, cbSize, m_cTotal, m_cbTotal));
+#endif
+
     /* We have to try to open even symlinks, cause they could
      * be symlinks to directories. */
+    PRTDIR hDir;
     rc = RTDirOpen(&hDir, pcszPath);
+
     /* The following error happens when this was a symlink
-     * to an file or a regular file. */
+     * to a file or a regular file. */
     if (   rc == VERR_PATH_NOT_FOUND
         || rc == VERR_NOT_A_DIRECTORY)
@@ -150,12 +151,14 @@
                                                       pszNewFile, &pszNewFile[cbBaseLen],
                                                       objInfo1.Attr.fMode, cbSize));
+                        m_cTotal++;
                         m_cbTotal += cbSize;
+#ifdef DEBUG_andy
+                        LogFlowFunc(("strSrcPath=%s, strDstPath=%s, fMode=0x%x, cbSize=%RU64, cTotal=%RU32, cbTotal=%zu\n",
+                                     pszNewFile, &pszNewFile[cbBaseLen], objInfo1.Attr.fMode, cbSize, m_cTotal, m_cbTotal));
+#endif
                     }
                     else /* Handle symlink directories. */
                         rc = appendPathRecursive(pszNewFile, cbBaseLen, fFlags);
-#ifdef DEBUG_andy
-                    LogFlowFunc(("strSrcPath=%s, strDstPath=%s, fMode=0x%x, cbSize=%RU64, cbTotal=%zu\n",
-                                 pszNewFile, &pszNewFile[cbBaseLen], objInfo1.Attr.fMode, cbSize, m_cbTotal));
-#endif
+
                     RTStrFree(pszNewFile);
                 }
@@ -166,4 +169,5 @@
 
             default:
+                /* Just ignore the rest. */
                 break;
         }
Index: /trunk/src/VBox/GuestHost/DragAndDrop/DnDURIObject.cpp
===================================================================
--- /trunk/src/VBox/GuestHost/DragAndDrop/DnDURIObject.cpp	(revision 55555)
+++ /trunk/src/VBox/GuestHost/DragAndDrop/DnDURIObject.cpp	(revision 55556)
@@ -37,5 +37,5 @@
 DnDURIObject::DnDURIObject(void)
     : m_Type(Unknown)
-    , m_fMode(0)
+    , m_fCreationMode(0)
     , m_cbSize(0)
     , m_cbProcessed(0)
@@ -51,5 +51,5 @@
     , m_strSrcPath(strSrcPath)
     , m_strTgtPath(strDstPath)
-    , m_fMode(fMode)
+    , m_fCreationMode(fMode)
     , m_cbSize(cbSize)
     , m_cbProcessed(0)
@@ -199,5 +199,8 @@
                         rc = RTFileGetSize(u.m_hFile, &m_cbSize);
                     if (RT_SUCCESS(rc))
+                    {
+                        LogFlowFunc(("cbSize=%RU64, fMode=%RU32\n", m_cbSize, m_fCreationMode));
                         m_cbProcessed = 0;
+                    }
                 }
                 else
@@ -345,10 +348,10 @@
     Close();
 
-    m_Type        = Unknown;
-    m_strSrcPath  = "";
-    m_strTgtPath  = "";
-    m_fMode       = 0;
-    m_cbSize      = 0;
-    m_cbProcessed = 0;
+    m_Type          = Unknown;
+    m_strSrcPath    = "";
+    m_strTgtPath    = "";
+    m_fCreationMode = 0;
+    m_cbSize        = 0;
+    m_cbProcessed   = 0;
 }
 
Index: /trunk/src/VBox/Main/include/GuestDnDPrivate.h
===================================================================
--- /trunk/src/VBox/Main/include/GuestDnDPrivate.h	(revision 55555)
+++ /trunk/src/VBox/Main/include/GuestDnDPrivate.h	(revision 55556)
@@ -20,4 +20,7 @@
 #define ____H_GUESTDNDPRIVATE
 
+#include <iprt/dir.h>
+#include <iprt/file.h>
+
 #include "VBox/hgcmsvc.h" /* For PVBOXHGCMSVCPARM. */
 #include "VBox/GuestHost/DragAndDrop.h"
@@ -66,4 +69,15 @@
 typedef struct GuestDnDData
 {
+    GuestDnDData(void)
+        : cbToProcess(0)
+        , cbProcessed(0) { }
+
+    void Reset(void)
+    {
+        vecData.clear();
+        cbToProcess = 0;
+        cbProcessed = 0;
+    }
+
     /** Array (vector) of guest DnD data. This might be an URI list, according
      *  to the format being set. */
@@ -73,5 +87,85 @@
     /** Overall size (in bytes) of processed file data. */
     uint64_t                  cbProcessed;
+
 } GuestDnDData;
+
+/**
+ * Structure for keeping around URI (list) data.
+ */
+typedef struct GuestDnDURIData
+{
+    GuestDnDURIData(void)
+        : pvScratchBuf(NULL)
+        , cbScratchBuf(0) { }
+
+    virtual ~GuestDnDURIData(void)
+    {
+        Reset();
+    }
+
+    void Reset(void)
+    {
+        strDropDir = "";
+        lstURI.Clear();
+        lstDirs.clear();
+        lstFiles.clear();
+        if (pvScratchBuf)
+        {
+            RTMemFree(pvScratchBuf);
+            pvScratchBuf = NULL;
+        }
+        cbScratchBuf = 0;
+    }
+
+    int Rollback(void)
+    {
+        if (strDropDir.isEmpty())
+            return VINF_SUCCESS;
+
+        int rc = VINF_SUCCESS;
+        int rc2;
+
+        /* Rollback by removing any stuff created.
+         * Note: Only remove empty directories, never ever delete
+         *       anything recursive here! Steam (tm) knows best ... :-) */
+        for (size_t i = 0; i < lstFiles.size(); i++)
+        {
+            rc2 = RTFileDelete(lstFiles.at(i).c_str());
+            if (RT_SUCCESS(rc))
+                rc = rc2;
+        }
+
+        for (size_t i = 0; i < lstDirs.size(); i++)
+        {
+            rc2 = RTDirRemove(lstDirs.at(i).c_str());
+            if (RT_SUCCESS(rc))
+                rc = rc2;
+        }
+
+        rc2 = RTDirRemove(strDropDir.c_str());
+        if (RT_SUCCESS(rc))
+            rc = rc2;
+
+        return rc;
+    }
+
+    /** Temporary drop directory on the host where to
+     *  put the files sent from the guest. */
+    com::Utf8Str                    strDropDir;
+    /** (Non-recursive) List of root URI objects to receive. */
+    DnDURIList                      lstURI;
+    /** Current object to receive. */
+    DnDURIObject                    objURI;
+    /** List for holding created directories in the case of a rollback. */
+    RTCList<RTCString>              lstDirs;
+    /** List for holding created files in the case of a rollback. */
+    RTCList<RTCString>              lstFiles;
+    /** Pointer to an optional scratch buffer to use for
+     *  doing the actual chunk transfers. */
+    void                           *pvScratchBuf;
+    /** Size (in bytes) of scratch buffer. */
+    size_t                          cbScratchBuf;
+
+} GuestDnDURIData;
 
 /**
@@ -94,17 +188,8 @@
      *  This can be arbitrary data or an URI list. */
     GuestDnDData                        mData;
+    /** URI data structure. */
+    GuestDnDURIData                     mURI;
     /** Callback event to use. */
     GuestDnDCallbackEvent               mCallback;
-    /** Struct for keeping data required for URI list processing. */
-    struct
-    {
-        /** List of all URI objects to send. */
-        DnDURIList                      lstURI;
-        /** Pointer to scratch buffer to use for
-         *  doing the actual chunk transfers. */
-        void                           *pvScratchBuf;
-        /** Size (in bytes) of scratch buffer. */
-        size_t                          cbScratchBuf;
-    } mURI;
 
 } SENDDATACTX, *PSENDDATACTX;
@@ -131,22 +216,8 @@
      *  This can be arbitrary data or an URI list. */
     GuestDnDData                        mData;
+    /** URI data structure. */
+    GuestDnDURIData                     mURI;
     /** Callback event to use. */
     GuestDnDCallbackEvent               mCallback;
-    /** Struct for keeping data required for URI list processing. */
-    struct
-    {
-        /** Temporary drop directory on the host where to
-         *  put the files sent from the guest. */
-        com::Utf8Str                    strDropDir;
-        /** (Non-recursive) List of root URI objects to receive. */
-        DnDURIList                      lstURI;
-        /** Current object to receive. */
-        DnDURIObject                    objURI;
-        /** List for holding created directories in the case of a rollback. */
-        RTCList<RTCString>              lstDirs;
-        /** List for holding created files in the case of a rollback. */
-        RTCList<RTCString>              lstFiles;
-
-    } mURI;
 
 } RECVDATACTX, *PRECVDATACTX;
Index: /trunk/src/VBox/Main/src-client/GuestDnDPrivate.cpp
===================================================================
--- /trunk/src/VBox/Main/src-client/GuestDnDPrivate.cpp	(revision 55555)
+++ /trunk/src/VBox/Main/src-client/GuestDnDPrivate.cpp	(revision 55556)
@@ -317,5 +317,5 @@
                  uStatus, uPercentage, rcOp));
 
-    int vrc = VINF_SUCCESS;
+    int rc = VINF_SUCCESS;
     if (!m_progress.isNull())
     {
@@ -383,6 +383,6 @@
     }
 
-    LogFlowFuncLeaveRC(vrc);
-    return vrc;
+    LogFlowFuncLeaveRC(rc);
+    return rc;
 }
 
Index: /trunk/src/VBox/Main/src-client/GuestDnDSourceImpl.cpp
===================================================================
--- /trunk/src/VBox/Main/src-client/GuestDnDSourceImpl.cpp	(revision 55555)
+++ /trunk/src/VBox/Main/src-client/GuestDnDSourceImpl.cpp	(revision 55556)
@@ -593,10 +593,13 @@
         if (RT_SUCCESS(rc))
         {
-            /** @todo Unescpae path before printing. */
-            LogRel2(("DnD: Transferring guest file to host: %s\n", pCtx->mURI.objURI.GetDestPath().c_str()));
-
             /* Note: Protocol v1 does not send any file sizes, so always 0. */
             if (mDataBase.mProtocolVersion >= 2)
                 rc = pCtx->mURI.objURI.SetSize(cbSize);
+
+            /** @todo Unescpae path before printing. */
+            LogRel2(("DnD: Transferring guest file to host: %s (%RU64 bytes, mode 0x%x)\n",
+                     pCtx->mURI.objURI.GetDestPath().c_str(), pCtx->mURI.objURI.GetSize(), pCtx->mURI.objURI.GetMode()));
+
+            /** @todo Set progress object title to current file being transferred? */
 
             if (!cbSize) /* 0-byte file? Close again. */
@@ -737,13 +740,10 @@
      * Reset any old data.
      */
-    pCtx->mData.vecData.clear();
-    pCtx->mData.cbToProcess = 0;
-    pCtx->mData.cbProcessed = 0;
-
-    pResp->reset();
-    pResp->resetProgress(m_pGuest);
+    pCtx->mData.Reset();
+    pCtx->mURI.Reset();
 
     /* Set the format we are going to retrieve to have it around
      * when retrieving the data later. */
+    pResp->reset();
     pResp->setFormat(pCtx->mFormat);
 
@@ -876,12 +876,14 @@
         return VERR_INVALID_POINTER;
 
-#define REGISTER_CALLBACK(x) \
+#define REGISTER_CALLBACK(x)                                    \
     rc = pResp->setCallback(x, i_receiveURIDataCallback, pCtx); \
-    if (RT_FAILURE(rc)) \
+    if (RT_FAILURE(rc))                                         \
         return rc;
 
-#define UNREGISTER_CALLBACK(x) \
-    rc = pResp->setCallback(x, NULL); \
-    AssertRC(rc);
+#define UNREGISTER_CALLBACK(x)                                  \
+    {                                                           \
+        int rc2 = pResp->setCallback(x, NULL);                  \
+        AssertRC(rc2);                                          \
+    }
 
     /*
@@ -927,4 +929,9 @@
             rc = pCtx->mCallback.Wait(msTimeout);
             LogFlowFunc(("URI callback done, rc=%Rrc\n", rc));
+            if (RT_SUCCESS(rc))
+            {
+                rc = pCtx->mCallback.Result();
+                LogFlowFunc(("Callback result is %Rrc\n", rc));
+            }
         }
 
@@ -946,16 +953,7 @@
     if (RT_FAILURE(rc))
     {
-        LogFlowFunc(("Rolling back ...\n"));
-
-        /* Rollback by removing any stuff created. */
-        for (size_t i = 0; i < pCtx->mURI.lstFiles.size(); ++i)
-            RTFileDelete(pCtx->mURI.lstFiles.at(i).c_str());
-        for (size_t i = 0; i < pCtx->mURI.lstDirs.size(); ++i)
-            RTDirRemove(pCtx->mURI.lstDirs.at(i).c_str());
-    }
-
-    /* Try removing (hopefully) empty drop directory in any case. */
-    if (pCtx->mURI.strDropDir.isNotEmpty())
-        RTDirRemove(pCtx->mURI.strDropDir.c_str());
+        int rc2 = pCtx->mURI.Rollback(); /** @todo Inform user on rollback failure? */
+        LogFlowFunc(("Rolling back ended with rc=%Rrc\n", rc2));
+    }
 
     LogFlowFuncLeaveRC(rc);
@@ -1121,6 +1119,6 @@
     }
 
-    LogFlowFunc(("cbProcessed=%RU64, cbToProcess=%RU64, fNotify=%RTbool\n",
-                 pCtx->mData.cbProcessed, pCtx->mData.cbToProcess, fNotify));
+    LogFlowFunc(("cbProcessed=%RU64, cbToProcess=%RU64, fNotify=%RTbool, rc=%Rrc\n",
+                 pCtx->mData.cbProcessed, pCtx->mData.cbToProcess, fNotify, rc));
 
     if (fNotify)
Index: /trunk/src/VBox/Main/src-client/GuestDnDTargetImpl.cpp
===================================================================
--- /trunk/src/VBox/Main/src-client/GuestDnDTargetImpl.cpp	(revision 55555)
+++ /trunk/src/VBox/Main/src-client/GuestDnDTargetImpl.cpp	(revision 55556)
@@ -737,4 +737,6 @@
                 LogRel2(("DnD: Transferring host file to guest: %s (%RU64 bytes, mode 0x%x)\n",
                          strPathSrc.c_str(), aFile.GetSize(), aFile.GetMode()));
+
+                /** @todo Set progress object title to current file being transferred? */
             }
             else
