Index: /trunk/include/VBox/GuestHost/DragAndDrop.h
===================================================================
--- /trunk/include/VBox/GuestHost/DragAndDrop.h	(revision 57775)
+++ /trunk/include/VBox/GuestHost/DragAndDrop.h	(revision 57776)
@@ -39,10 +39,33 @@
 
 /**
- * Structure for maintaining a "dropped files" directory
+ * Class for maintaining a "dropped files" directory
  * on the host or guest. This will contain all received files & directories
  * for a single drag and drop operation.
+ *
+ * In case of a failed drag and drop operation this class can also
+ * perform a gentle rollback if required.
  */
-typedef struct DNDDIRDROPPEDFILES
+class DnDDroppedFiles
 {
+
+public:
+
+    DnDDroppedFiles(void);
+    DnDDroppedFiles(const char *pszPath, uint32_t fFlags);
+    virtual ~DnDDroppedFiles(void);
+
+public:
+
+    int AddFile(const char *pszFile);
+    int AddDir(const char *pszDir);
+    bool IsOpen(void) const;
+    int OpenEx(const char *pszPath, uint32_t fFlags);
+    int OpenTemp(uint32_t fFlags);
+    const char *GetDirAbs(void) const;
+    int Reset(bool fDeleteContent);
+    int Rollback(void);
+
+protected:
+
     /** Directory handle for drop directory. */
     PRTDIR                       hDir;
@@ -56,15 +79,5 @@
     /** List for holding created files in the case of a rollback. */
     RTCList<RTCString>           lstFiles;
-
-} DNDDIRDROPPEDFILES, *PDNDDIRDROPPEDFILES;
-
-int DnDDirDroppedAddFile(PDNDDIRDROPPEDFILES pDir, const char *pszFile);
-int DnDDirDroppedAddDir(PDNDDIRDROPPEDFILES pDir, const char *pszDir);
-int DnDDirDroppedFilesCreateAndOpenEx(const char *pszPath, uint32_t fFlags, PDNDDIRDROPPEDFILES *ppDir);
-int DnDDirDroppedFilesCreateAndOpenTemp(uint32_t fFlags, PDNDDIRDROPPEDFILES *ppDir);
-int DnDDirDroppedFilesClose(PDNDDIRDROPPEDFILES pDir, bool fRemove);
-void DnDDirDroppedFilesDestroy(PDNDDIRDROPPEDFILES pDir);
-const char *DnDDirDroppedFilesGetDirAbs(PDNDDIRDROPPEDFILES pDir);
-int DnDDirDroppedFilesRollback(PDNDDIRDROPPEDFILES pDir);
+};
 
 bool DnDMIMEHasFileURLs(const char *pcszFormat, size_t cchFormatMax);
Index: /trunk/src/VBox/Additions/common/VBoxGuestLib/VBoxGuestR3LibDragAndDrop.cpp
===================================================================
--- /trunk/src/VBox/Additions/common/VBoxGuestLib/VBoxGuestR3LibDragAndDrop.cpp	(revision 57775)
+++ /trunk/src/VBox/Additions/common/VBoxGuestLib/VBoxGuestR3LibDragAndDrop.cpp	(revision 57776)
@@ -373,9 +373,14 @@
      * Create and query the (unique) drop target directory in the user's temporary directory.
      */
-    PDNDDIRDROPPEDFILES pDroppedFiles;
-    const char *pszDropDir = NULL;
-    int rc = DnDDirDroppedFilesCreateAndOpenTemp(0 /* fFlags */, &pDroppedFiles);
-    if (RT_SUCCESS(rc))
-        pszDropDir = DnDDirDroppedFilesGetDirAbs(pDroppedFiles);
+    DnDDroppedFiles droppedFiles;
+    int rc = droppedFiles.OpenTemp(0 /* fFlags */);
+    if (RT_FAILURE(rc))
+    {
+        RTMemFree(pvChunk);
+        return VERR_NO_MEMORY;
+    }
+
+    const char *pszDropDir = droppedFiles.GetDirAbs();
+    AssertPtr(pszDropDir);
 
     /*
@@ -421,5 +426,5 @@
                         rc = RTDirCreate(pszPathAbs, fCreationMode, 0);
                         if (RT_SUCCESS(rc))
-                            rc = DnDDirDroppedAddDir(pDroppedFiles, pszPathAbs);
+                            rc = droppedFiles.AddDir(pszPathAbs);
 
                         RTStrFree(pszPathAbs);
@@ -488,5 +493,5 @@
                                 if (RT_SUCCESS(rc))
                                 {
-                                    rc = DnDDirDroppedAddFile(pDroppedFiles, strPathAbs.c_str());
+                                    rc = droppedFiles.AddFile(strPathAbs.c_str());
                                     if (RT_SUCCESS(rc))
                                     {
@@ -571,5 +576,5 @@
     if (RT_FAILURE(rc))
     {
-        int rc2 = DnDDirDroppedFilesRollback(pDroppedFiles);
+        int rc2 = droppedFiles.Rollback();
         AssertRC(rc2); /* Not fatal, don't report back to host. */
     }
@@ -620,9 +625,7 @@
      * by the client's drag'n drop operation lateron.
      */
-    int rc2 = DnDDirDroppedFilesClose(pDroppedFiles, false);
+    int rc2 = droppedFiles.Reset(false /* fRemoveDropDir */);
     if (RT_FAILURE(rc2)) /* Not fatal, don't report back to host. */
         LogFlowFunc(("Closing dropped files directory failed with %Rrc\n", rc2));
-
-    DnDDirDroppedFilesDestroy(pDroppedFiles);
 
     LogFlowFuncLeaveRC(rc);
Index: unk/src/VBox/GuestHost/DragAndDrop/DnDDir.cpp
===================================================================
--- /trunk/src/VBox/GuestHost/DragAndDrop/DnDDir.cpp	(revision 57775)
+++ 	(revision )
@@ -1,254 +1,0 @@
-/* $Id$ */
-/** @file
- * DnD: Directory handling.
- */
-
-/*
- * Copyright (C) 2014-2015 Oracle Corporation
- *
- * This file is part of VirtualBox Open Source Edition (OSE), as
- * available from http://www.virtualbox.org. This file is free software;
- * you can redistribute it and/or modify it under the terms of the GNU
- * General Public License (GPL) as published by the Free Software
- * Foundation, in version 2 as it comes in the "COPYING" file of the
- * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
- * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
- */
-
-
-/*********************************************************************************************************************************
-*   Header Files                                                                                                                 *
-*********************************************************************************************************************************/
-
-#include <iprt/assert.h>
-#include <iprt/dir.h>
-#include <iprt/path.h>
-#include <iprt/string.h>
-
-#include <VBox/GuestHost/DragAndDrop.h>
-
-int DnDDirDroppedAddFile(PDNDDIRDROPPEDFILES pDir, const char *pszFile)
-{
-    AssertPtrReturn(pDir, VERR_INVALID_POINTER);
-    AssertPtrReturn(pszFile, VERR_INVALID_POINTER);
-
-    if (!pDir->lstFiles.contains(pszFile))
-        pDir->lstFiles.append(pszFile);
-    return VINF_SUCCESS;
-}
-
-int DnDDirDroppedAddDir(PDNDDIRDROPPEDFILES pDir, const char *pszDir)
-{
-    AssertPtrReturn(pDir, VERR_INVALID_POINTER);
-    AssertPtrReturn(pszDir, VERR_INVALID_POINTER);
-
-    if (!pDir->lstDirs.contains(pszDir))
-        pDir->lstDirs.append(pszDir);
-    return VINF_SUCCESS;
-}
-
-static int dndDirDroppedFilesCreate(uint32_t fFlags, PDNDDIRDROPPEDFILES *ppDir)
-{
-    AssertReturn(fFlags == 0, VERR_INVALID_PARAMETER); /* Flags not supported yet. */
-    AssertPtrReturn(ppDir, VERR_INVALID_POINTER);
-
-    PDNDDIRDROPPEDFILES pDir = (PDNDDIRDROPPEDFILES)RTMemAlloc(sizeof(DNDDIRDROPPEDFILES));
-    if (pDir)
-    {
-        pDir->hDir  = NULL;
-        pDir->fOpen = false;
-
-        *ppDir = pDir;
-        return VINF_SUCCESS;
-    }
-
-    return VERR_NO_MEMORY;
-}
-
-int DnDDirDroppedFilesCreateAndOpenEx(const char *pszPath, uint32_t fFlags, PDNDDIRDROPPEDFILES *ppDir)
-{
-    AssertPtrReturn(pszPath, VERR_INVALID_POINTER);
-    AssertPtrReturn(ppDir, VERR_INVALID_POINTER);
-
-    PDNDDIRDROPPEDFILES pDir;
-    int rc = dndDirDroppedFilesCreate(fFlags, &pDir);
-    if (RT_FAILURE(rc))
-        return rc;
-
-    do
-    {
-        char pszDropDir[RTPATH_MAX];
-        if (RTStrPrintf(pszDropDir, sizeof(pszDropDir), "%s", pszPath) <= 0)
-        {
-            rc = VERR_NO_MEMORY;
-            break;
-        }
-
-        /** @todo On Windows we also could use the registry to override
-         *        this path, on Posix a dotfile and/or a guest property
-         *        can be used. */
-
-        /* Append our base drop directory. */
-        int rc = RTPathAppend(pszDropDir, sizeof(pszDropDir), "VirtualBox Dropped Files"); /** @todo Make this tag configurable? */
-        if (RT_FAILURE(rc))
-            break;
-
-        /* Create it when necessary. */
-        if (!RTDirExists(pszDropDir))
-        {
-            rc = RTDirCreateFullPath(pszDropDir, RTFS_UNIX_IRWXU);
-            if (RT_FAILURE(rc))
-                break;
-        }
-
-        /* The actually drop directory consist of the current time stamp and a
-         * unique number when necessary. */
-        char pszTime[64];
-        RTTIMESPEC time;
-        if (!RTTimeSpecToString(RTTimeNow(&time), pszTime, sizeof(pszTime)))
-        {
-            rc = VERR_BUFFER_OVERFLOW;
-            break;
-        }
-
-        rc = DnDPathSanitizeFilename(pszTime, sizeof(pszTime));
-        if (RT_FAILURE(rc))
-            break;
-
-        rc = RTPathAppend(pszDropDir, sizeof(pszDropDir), pszTime);
-        if (RT_FAILURE(rc))
-            break;
-
-        /* Create it (only accessible by the current user) */
-        rc = RTDirCreateUniqueNumbered(pszDropDir, sizeof(pszDropDir), RTFS_UNIX_IRWXU, 3, '-');
-        if (RT_SUCCESS(rc))
-        {
-            PRTDIR phDir;
-            rc = RTDirOpen(&phDir, pszDropDir);
-            if (RT_SUCCESS(rc))
-            {
-                pDir->hDir       = phDir;
-                pDir->strPathAbs = pszDropDir;
-                pDir->fOpen      = true;
-            }
-        }
-
-    } while (0);
-
-    if (RT_SUCCESS(rc))
-    {
-        *ppDir = pDir;
-    }
-    else
-        DnDDirDroppedFilesDestroy(pDir);
-
-    return rc;
-}
-
-int DnDDirDroppedFilesCreateAndOpenTemp(uint32_t fFlags, PDNDDIRDROPPEDFILES *ppDir)
-{
-    AssertReturn(fFlags == 0, VERR_INVALID_PARAMETER); /* Flags not supported yet. */
-    AssertPtrReturn(ppDir, VERR_INVALID_POINTER);
-
-    PDNDDIRDROPPEDFILES pDir;
-
-    /*
-     * Get the user's temp directory. Don't use the user's root directory (or
-     * something inside it) because we don't know for how long/if the data will
-     * be kept after the guest OS used it.
-     */
-    char szTemp[RTPATH_MAX];
-    int rc = RTPathTemp(szTemp, sizeof(szTemp));
-    if (RT_SUCCESS(rc))
-        rc = DnDDirDroppedFilesCreateAndOpenEx(szTemp, fFlags, &pDir);
-
-    if (RT_SUCCESS(rc))
-    {
-        *ppDir = pDir;
-    }
-    else
-        DnDDirDroppedFilesDestroy(pDir);
-
-    return rc;
-}
-
-void DnDDirDroppedFilesDestroy(PDNDDIRDROPPEDFILES pDir)
-{
-    AssertPtrReturnVoid(pDir);
-
-    RTMemFree(pDir);
-}
-
-int DnDDirDroppedFilesClose(PDNDDIRDROPPEDFILES pDir, bool fRemove)
-{
-    AssertPtrReturn(pDir, VERR_INVALID_POINTER);
-
-    int rc = VINF_SUCCESS;
-    if (pDir->fOpen)
-    {
-        rc = RTDirClose(pDir->hDir);
-        if (RT_SUCCESS(rc))
-        {
-            pDir->fOpen = false;
-            pDir->hDir  = NULL;
-        }
-    }
-    if (RT_SUCCESS(rc))
-    {
-        pDir->lstDirs.clear();
-        pDir->lstFiles.clear();
-
-        if (   fRemove
-            && pDir->strPathAbs.isNotEmpty())
-        {
-            /* Try removing the (empty) drop directory in any case. */
-            rc = RTDirRemove(pDir->strPathAbs.c_str());
-            if (RT_SUCCESS(rc)) /* Only clear if successfully removed. */
-                pDir->strPathAbs = "";
-        }
-    }
-
-    return rc;
-}
-
-const char *DnDDirDroppedFilesGetDirAbs(PDNDDIRDROPPEDFILES pDir)
-{
-    AssertPtrReturn(pDir, NULL);
-    return pDir->strPathAbs.c_str();
-}
-
-int DnDDirDroppedFilesRollback(PDNDDIRDROPPEDFILES pDir)
-{
-    AssertPtrReturn(pDir, VERR_INVALID_POINTER);
-
-    if (pDir->strPathAbs.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 < pDir->lstFiles.size(); i++)
-    {
-        rc2 = RTFileDelete(pDir->lstFiles.at(i).c_str());
-        if (RT_SUCCESS(rc))
-            rc = rc2;
-    }
-
-    for (size_t i = 0; i < pDir->lstDirs.size(); i++)
-    {
-        rc2 = RTDirRemove(pDir->lstDirs.at(i).c_str());
-        if (RT_SUCCESS(rc))
-            rc = rc2;
-    }
-
-    /* Try to remove the empty root dropped files directory as well. */
-    rc2 = RTDirRemove(pDir->strPathAbs.c_str());
-    if (RT_SUCCESS(rc))
-        rc = rc2;
-
-    return rc;
-}
-
Index: /trunk/src/VBox/GuestHost/DragAndDrop/DnDDroppedFiles.cpp
===================================================================
--- /trunk/src/VBox/GuestHost/DragAndDrop/DnDDroppedFiles.cpp	(revision 57776)
+++ /trunk/src/VBox/GuestHost/DragAndDrop/DnDDroppedFiles.cpp	(revision 57776)
@@ -0,0 +1,222 @@
+/* $Id$ */
+/** @file
+ * DnD: Directory handling.
+ */
+
+/*
+ * Copyright (C) 2014-2015 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+
+/*********************************************************************************************************************************
+*   Header Files                                                                                                                 *
+*********************************************************************************************************************************/
+
+#include <iprt/assert.h>
+#include <iprt/dir.h>
+#include <iprt/path.h>
+#include <iprt/string.h>
+
+#include <VBox/GuestHost/DragAndDrop.h>
+
+DnDDroppedFiles::DnDDroppedFiles(void)
+    : hDir(NULL)
+    , fOpen(false) { }
+
+DnDDroppedFiles::DnDDroppedFiles(const char *pszPath, uint32_t fFlags)
+    : hDir(NULL)
+    , fOpen(false)
+{
+    OpenEx(pszPath, fFlags);
+}
+
+DnDDroppedFiles::~DnDDroppedFiles(void)
+{
+    Reset(true /* fRemoveDropDir */);
+}
+
+int DnDDroppedFiles::AddFile(const char *pszFile)
+{
+    AssertPtrReturn(pszFile, VERR_INVALID_POINTER);
+
+    if (!this->lstFiles.contains(pszFile))
+        this->lstFiles.append(pszFile);
+    return VINF_SUCCESS;
+}
+
+int DnDDroppedFiles::AddDir(const char *pszDir)
+{
+    AssertPtrReturn(pszDir, VERR_INVALID_POINTER);
+
+    if (!this->lstDirs.contains(pszDir))
+        this->lstDirs.append(pszDir);
+    return VINF_SUCCESS;
+}
+
+const char *DnDDroppedFiles::GetDirAbs(void) const
+{
+    return this->strPathAbs.c_str();
+}
+
+bool DnDDroppedFiles::IsOpen(void) const
+{
+    return this->fOpen;
+}
+
+int DnDDroppedFiles::OpenEx(const char *pszPath, uint32_t fFlags)
+{
+    AssertPtrReturn(pszPath, VERR_INVALID_POINTER);
+    AssertReturn(fFlags == 0, VERR_INVALID_PARAMETER); /* Flags not supported yet. */
+
+    int rc;
+
+    do
+    {
+        char pszDropDir[RTPATH_MAX];
+        size_t cchDropDir = RTStrPrintf(pszDropDir, sizeof(pszDropDir), "%s", pszPath);
+
+        /** @todo On Windows we also could use the registry to override
+         *        this path, on Posix a dotfile and/or a guest property
+         *        can be used. */
+
+        /* Append our base drop directory. */
+        rc = RTPathAppend(pszDropDir, sizeof(pszDropDir), "VirtualBox Dropped Files"); /** @todo Make this tag configurable? */
+        if (RT_FAILURE(rc))
+            break;
+
+        /* Create it when necessary. */
+        if (!RTDirExists(pszDropDir))
+        {
+            rc = RTDirCreateFullPath(pszDropDir, RTFS_UNIX_IRWXU);
+            if (RT_FAILURE(rc))
+                break;
+        }
+
+        /* The actually drop directory consist of the current time stamp and a
+         * unique number when necessary. */
+        char pszTime[64];
+        RTTIMESPEC time;
+        if (!RTTimeSpecToString(RTTimeNow(&time), pszTime, sizeof(pszTime)))
+        {
+            rc = VERR_BUFFER_OVERFLOW;
+            break;
+        }
+
+        rc = DnDPathSanitizeFilename(pszTime, sizeof(pszTime));
+        if (RT_FAILURE(rc))
+            break;
+
+        rc = RTPathAppend(pszDropDir, sizeof(pszDropDir), pszTime);
+        if (RT_FAILURE(rc))
+            break;
+
+        /* Create it (only accessible by the current user) */
+        rc = RTDirCreateUniqueNumbered(pszDropDir, sizeof(pszDropDir), RTFS_UNIX_IRWXU, 3, '-');
+        if (RT_SUCCESS(rc))
+        {
+            PRTDIR phDir;
+            rc = RTDirOpen(&phDir, pszDropDir);
+            if (RT_SUCCESS(rc))
+            {
+                this->hDir       = phDir;
+                this->strPathAbs = pszDropDir;
+                this->fOpen      = true;
+            }
+        }
+
+    } while (0);
+
+    return rc;
+}
+
+int DnDDroppedFiles::OpenTemp(uint32_t fFlags)
+{
+    AssertReturn(fFlags == 0, VERR_INVALID_PARAMETER); /* Flags not supported yet. */
+
+    /*
+     * Get the user's temp directory. Don't use the user's root directory (or
+     * something inside it) because we don't know for how long/if the data will
+     * be kept after the guest OS used it.
+     */
+    char szTemp[RTPATH_MAX];
+    int rc = RTPathTemp(szTemp, sizeof(szTemp));
+    if (RT_SUCCESS(rc))
+        rc = OpenEx(szTemp, fFlags);
+
+    return rc;
+}
+
+int DnDDroppedFiles::Reset(bool fRemoveDropDir)
+{
+    int rc = VINF_SUCCESS;
+    if (this->fOpen)
+    {
+        rc = RTDirClose(this->hDir);
+        if (RT_SUCCESS(rc))
+        {
+            this->fOpen = false;
+            this->hDir  = NULL;
+        }
+    }
+    if (RT_SUCCESS(rc))
+    {
+        this->lstDirs.clear();
+        this->lstFiles.clear();
+
+        if (   fRemoveDropDir
+            && this->strPathAbs.isNotEmpty())
+        {
+            /* Try removing the (empty) drop directory in any case. */
+            rc = RTDirRemove(this->strPathAbs.c_str());
+            if (RT_SUCCESS(rc)) /* Only clear if successfully removed. */
+                this->strPathAbs = "";
+        }
+    }
+
+    return rc;
+}
+
+int DnDDroppedFiles::Rollback(void)
+{
+    if (this->strPathAbs.isEmpty())
+        return VINF_SUCCESS;
+
+    Assert(this->fOpen);
+    Assert(this->hDir != NULL);
+
+    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 < this->lstFiles.size(); i++)
+    {
+        rc2 = RTFileDelete(this->lstFiles.at(i).c_str());
+        if (RT_SUCCESS(rc))
+            rc = rc2;
+    }
+
+    for (size_t i = 0; i < this->lstDirs.size(); i++)
+    {
+        rc2 = RTDirRemove(this->lstDirs.at(i).c_str());
+        if (RT_SUCCESS(rc))
+            rc = rc2;
+    }
+
+    /* Try to remove the empty root dropped files directory as well. */
+    rc2 = RTDirRemove(this->strPathAbs.c_str());
+    if (RT_SUCCESS(rc))
+        rc = rc2;
+
+    return rc;
+}
+
Index: /trunk/src/VBox/GuestHost/DragAndDrop/Makefile.kmk
===================================================================
--- /trunk/src/VBox/GuestHost/DragAndDrop/Makefile.kmk	(revision 57775)
+++ /trunk/src/VBox/GuestHost/DragAndDrop/Makefile.kmk	(revision 57776)
@@ -20,5 +20,5 @@
 
 VBOX_DND_GUESTHOST_FILES := \
-	DnDDir.cpp \
+	DnDDroppedFiles.cpp \
 	DnDMIME.cpp \
 	DnDPath.cpp \
Index: /trunk/src/VBox/Main/include/GuestDnDPrivate.h
===================================================================
--- /trunk/src/VBox/Main/include/GuestDnDPrivate.h	(revision 57775)
+++ /trunk/src/VBox/Main/include/GuestDnDPrivate.h	(revision 57776)
@@ -138,6 +138,5 @@
 {
     GuestDnDURIData(void)
-        : pDropDir(NULL)
-        , pvScratchBuf(NULL)
+        : pvScratchBuf(NULL)
         , cbScratchBuf(0) { }
 
@@ -159,7 +158,9 @@
     }
 
-    void * GetBufferMutable(void) { return pvScratchBuf; }
-
-    size_t GetBufferSize(void) { return cbScratchBuf; }
+    const void *GetBuffer(void) const { return pvScratchBuf; }
+
+    void *GetBufferMutable(void) { return pvScratchBuf; }
+
+    size_t GetBufferSize(void) const { return cbScratchBuf; }
 
     void Reset(void)
@@ -168,14 +169,8 @@
         objCtx.Reset();
 
-        if (pDropDir)
-        {
-            int rc2 = DnDDirDroppedFilesRollback(pDropDir);
-            AssertRC(rc2);
-            rc2 = DnDDirDroppedFilesClose(pDropDir, true /* fRemove */);
-            AssertRC(rc2);
-
-            DnDDirDroppedFilesDestroy(pDropDir);
-            pDropDir = NULL;
-        }
+        int rc2 = droppedFiles.Rollback();
+        AssertRC(rc2);
+        rc2 = droppedFiles.Reset(true /* fRemoveDropDir */);
+        AssertRC(rc2);
 
         if (pvScratchBuf)
@@ -188,6 +183,6 @@
     }
 
-    /** Pointer to dropped files object. */
-    PDNDDIRDROPPEDFILES             pDropDir;
+    /** Handles all drop files for this operation. */
+    DnDDroppedFiles                 droppedFiles;
     /** (Non-recursive) List of URI objects to handle. */
     DnDURIList                      lstURI;
Index: /trunk/src/VBox/Main/src-client/GuestDnDSourceImpl.cpp
===================================================================
--- /trunk/src/VBox/Main/src-client/GuestDnDSourceImpl.cpp	(revision 57775)
+++ /trunk/src/VBox/Main/src-client/GuestDnDSourceImpl.cpp	(revision 57776)
@@ -419,5 +419,6 @@
         if (fHasURIList)
         {
-            Utf8Str strURIs = pCtx->mURI.lstURI.RootToString(RTCString(DnDDirDroppedFilesGetDirAbs(pCtx->mURI.pDropDir)));
+            const char *pszDroppedFilesDir = pCtx->mURI.droppedFiles.GetDirAbs();
+            Utf8Str strURIs = pCtx->mURI.lstURI.RootToString(RTCString(pszDroppedFilesDir));
             cbData = strURIs.length();
 
@@ -604,5 +605,7 @@
 
     int rc;
-    char *pszDir = RTPathJoinA(DnDDirDroppedFilesGetDirAbs(pCtx->mURI.pDropDir), pszPath);
+
+    const char *pszDroppedFilesDir = pCtx->mURI.droppedFiles.GetDirAbs();
+    char *pszDir = RTPathJoinA(pszDroppedFilesDir, pszPath);
     if (pszDir)
     {
@@ -662,6 +665,8 @@
         }
 
+        const char *pszDroppedFilesDir = pCtx->mURI.droppedFiles.GetDirAbs();
+
         char pszPathAbs[RTPATH_MAX];
-        rc = RTPathJoin(pszPathAbs, sizeof(pszPathAbs), DnDDirDroppedFilesGetDirAbs(pCtx->mURI.pDropDir), pszPath);
+        rc = RTPathJoin(pszPathAbs, sizeof(pszPathAbs), pszDroppedFilesDir, pszPath);
         if (RT_FAILURE(rc))
         {
@@ -1034,10 +1039,12 @@
     REGISTER_CALLBACK(DragAndDropSvc::GUEST_DND_GH_SND_FILE_DATA);
 
+    DnDDroppedFiles &droppedFiles = pCtx->mURI.droppedFiles;
+
     do
     {
-        rc = DnDDirDroppedFilesCreateAndOpenTemp(0 /* fFlags */, &pCtx->mURI.pDropDir);
+        rc = droppedFiles.OpenTemp(0 /* fFlags */);
         if (RT_FAILURE(rc))
             break;
-        LogFlowFunc(("rc=%Rrc, strDropDir=%s\n", rc, DnDDirDroppedFilesGetDirAbs(pCtx->mURI.pDropDir)));
+        LogFlowFunc(("rc=%Rrc, strDropDir=%s\n", rc, droppedFiles.GetDirAbs()));
         if (RT_FAILURE(rc))
             break;
@@ -1100,19 +1107,13 @@
     }
 
-    if (pCtx->mURI.pDropDir)
-    {
-        if (RT_FAILURE(rc))
-        {
-            rc2 = DnDDirDroppedFilesRollback(pCtx->mURI.pDropDir); /** @todo Inform user on rollback failure? */
-            LogFlowFunc(("Rolling back ended with rc=%Rrc\n", rc2));
-        }
-
-        rc2 = DnDDirDroppedFilesClose(pCtx->mURI.pDropDir, RT_FAILURE(rc) ? true : false /* fRemove */);
-        if (RT_SUCCESS(rc))
-            rc = rc2;
-
-        DnDDirDroppedFilesDestroy(pCtx->mURI.pDropDir);
-        pCtx->mURI.pDropDir = NULL;
-    }
+    if (RT_FAILURE(rc))
+    {
+        rc2 = droppedFiles.Rollback(); /** @todo Inform user on rollback failure? */
+        LogFlowFunc(("Rolling back ended with rc=%Rrc\n", rc2));
+    }
+
+    rc2 = droppedFiles.Reset(RT_FAILURE(rc) ? true : false /* fRemoveDropDir */);
+    if (RT_SUCCESS(rc))
+        rc = rc2;
 
     LogFlowFuncLeaveRC(rc);
