Index: /trunk/include/VBox/GuestHost/SharedClipboard-uri.h
===================================================================
--- /trunk/include/VBox/GuestHost/SharedClipboard-uri.h	(revision 79671)
+++ /trunk/include/VBox/GuestHost/SharedClipboard-uri.h	(revision 79672)
@@ -370,4 +370,21 @@
 
 /**
+ * Structure for keeping Shared Clipboard list root entries.
+ */
+typedef struct _VBOXCLIPBOARDROOTS
+{
+    /** Roots listing flags; unused at the moment. */
+    uint32_t fRoots;
+    /** Boolean indicating that more root items are following. */
+    bool     fMore;
+    /** Number of root items in this message. */
+    uint32_t cRoots;
+    /** Size (in bytes) of string list. */
+    uint32_t cbRoots;
+    /** String list (separated with \r\n) containing the root items. */
+    char    *pszRoots;
+} VBOXCLIPBOARDROOTS, *PVBOXCLIPBOARDROOTS;
+
+/**
  * Structure for maintaining Shared Clipboard list open paramters.
  */
@@ -408,4 +425,8 @@
 typedef struct _VBOXCLIPBOARDLISTENTRY
 {
+    /** Entry name. */
+    char    *pszName;
+    /** Size (in bytes) of entry name. */
+    uint32_t cbName;
     /** Information flag(s). */
     uint32_t fInfo;
@@ -415,4 +436,6 @@
     void    *pvInfo;
 } VBOXCLIPBOARDLISTENTRY, *PVBOXCLIPBOARDLISTENTRY;
+
+#define VBOXCLIPBOARDLISTENTRY_MAX_NAME     RTPATH_MAX
 
 /**
@@ -556,4 +579,8 @@
 int SharedClipboardPathSanitize(char *pszPath, size_t cbPath);
 
+PVBOXCLIPBOARDROOTS SharedClipboardURIRootsDup(PVBOXCLIPBOARDROOTS pRoots);
+int SharedClipboardURIRootsInit(PVBOXCLIPBOARDROOTS pRoots);
+void SharedClipboardURIRootsDestroy(PVBOXCLIPBOARDROOTS pRoots);
+
 int SharedClipboardURIListHdrAlloc(PVBOXCLIPBOARDLISTHDR *ppListHdr);
 void SharedClipboardURIListHdrFree(PVBOXCLIPBOARDLISTHDR pListHdr);
@@ -665,4 +692,5 @@
 {
     SHAREDCLIPBOARDURITRANSFEREVENTTYPE_UNKNOWN,
+    SHAREDCLIPBOARDURITRANSFEREVENTTYPE_GET_ROOTS,
     SHAREDCLIPBOARDURITRANSFEREVENTTYPE_LIST_OPEN,
     SHAREDCLIPBOARDURITRANSFEREVENTTYPE_LIST_CLOSE,
@@ -689,5 +717,5 @@
 {
     VBOXCLIPBOARDLISTOPENPARMS OpenParms;
-    RTFMODE                     fMode;
+    RTFMODE                    fMode;
     union
     {
@@ -718,5 +746,10 @@
 typedef std::map<SHAREDCLIPBOARDLISTHANDLE, SHAREDCLIPBOARDURILISTHANDLEINFO *> SharedClipboardURIListMap;
 
+/** Map of URI object handles.
+ *  The key specifies the object handle. */
 typedef std::map<SHAREDCLIPBOARDOBJHANDLE, SHAREDCLIPBOARDURILISTHANDLEINFO *> SharedClipboardURIObjMap;
+
+/** List of URI list root entries. */
+typedef RTCList<RTCString> SharedClipboardURIListRootEntries;
 
 /**
@@ -770,4 +803,5 @@
 SHAREDCLIPBOARDPROVIDERFUNCDECLVOID(TRANSFEROPEN)
 SHAREDCLIPBOARDPROVIDERFUNCDECLVOID(TRANSFERCLOSE)
+SHAREDCLIPBOARDPROVIDERFUNCDECL(GETROOTS, char **ppapszRoots, uint32_t *pcRoots)
 SHAREDCLIPBOARDPROVIDERFUNCDECL(LISTOPEN, PVBOXCLIPBOARDLISTOPENPARMS pOpenParms, PSHAREDCLIPBOARDLISTHANDLE phList)
 SHAREDCLIPBOARDPROVIDERFUNCDECL(LISTCLOSE, SHAREDCLIPBOARDLISTHANDLE hList);
@@ -791,4 +825,5 @@
     SHAREDCLIPBOARDPROVIDERFUNCMEMBER(TRANSFEROPEN, pfnTransferOpen);
     SHAREDCLIPBOARDPROVIDERFUNCMEMBER(TRANSFERCLOSE, pfnTransferClose);
+    SHAREDCLIPBOARDPROVIDERFUNCMEMBER(GETROOTS, pfnGetRoots);
     SHAREDCLIPBOARDPROVIDERFUNCMEMBER(LISTOPEN, pfnListOpen);
     SHAREDCLIPBOARDPROVIDERFUNCMEMBER(LISTCLOSE, pfnListClose);
@@ -907,5 +942,9 @@
     /** Events related to this transfer. */
     SharedClipboardURITransferEventMap *pMapEvents;
+    /** Map of all lists related to this transfer. */
     SharedClipboardURIListMap          *pMapLists;
+    /** List of root entries of this transfer. */
+    SharedClipboardURIListRootEntries   lstRootEntries;
+    /** Map of all objects related to this transfer. */
     SharedClipboardURIObjMap           *pMapObj;
     /** The transfer's own (local) area, if any (can be NULL if not needed).
@@ -970,8 +1009,11 @@
 
 int SharedClipboardURITransferPrepare(PSHAREDCLIPBOARDURITRANSFER pTransfer);
+int SharedClipboardURITransferSetData(PSHAREDCLIPBOARDURITRANSFER pTransfer, SharedClipboardURIListRootEntries *pEntries);
 int SharedClipboardURITransferSetInterface(PSHAREDCLIPBOARDURITRANSFER pTransfer,
                                            PSHAREDCLIPBOARDPROVIDERCREATIONCTX pCreationCtx);
+int SharedClipboardURILTransferSetRoots(PSHAREDCLIPBOARDURITRANSFER pTransfer, const char *papszRoots, size_t cbRoots);
 void SharedClipboardURITransferReset(PSHAREDCLIPBOARDURITRANSFER pTransfer);
 SharedClipboardArea *SharedClipboardURITransferGetArea(PSHAREDCLIPBOARDURITRANSFER pTransfer);
+int SharedClipboardURILTransferGetRoots(PSHAREDCLIPBOARDURITRANSFER pTransfer, char **ppapszRoots, uint32_t *pcRoots);
 SHAREDCLIPBOARDSOURCE SharedClipboardURITransferGetSource(PSHAREDCLIPBOARDURITRANSFER pTransfer);
 SHAREDCLIPBOARDURITRANSFERSTATUS SharedClipboardURITransferGetStatus(PSHAREDCLIPBOARDURITRANSFER pTransfer);
Index: /trunk/include/VBox/HostServices/VBoxClipboardSvc.h
===================================================================
--- /trunk/include/VBox/HostServices/VBoxClipboardSvc.h	(revision 79671)
+++ /trunk/include/VBox/HostServices/VBoxClipboardSvc.h	(revision 79672)
@@ -75,28 +75,30 @@
 /** Initiates a new transfer (read / write) on the guest side. */
 #define VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_TRANSFER_START     50
+/** Requests reading the root entries from the guest. */
+#define VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_ROOTS              51
 /** Open an URI list on the guest side. */
-#define VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_LIST_OPEN          51
+#define VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_LIST_OPEN          52
 /** Closes a formerly opened URI list on the guest side. */
-#define VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_LIST_CLOSE         52
+#define VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_LIST_CLOSE         53
 /** Reads a list header from the guest. */
-#define VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_LIST_HDR_READ      53
+#define VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_LIST_HDR_READ      54
 /** Writes a list header to the guest. */
-#define VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_LIST_HDR_WRITE     54
+#define VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_LIST_HDR_WRITE     55
 /** Reads a list entry from the guest. */
-#define VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_LIST_ENTRY_READ    55
+#define VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_LIST_ENTRY_READ    56
 /** Writes a list entry to the guest. */
-#define VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_LIST_ENTRY_WRITE   56
+#define VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_LIST_ENTRY_WRITE   57
 /** Open an URI object on the guest side. */
-#define VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_OBJ_OPEN           57
+#define VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_OBJ_OPEN           58
 /** Closes a formerly opened URI object on the guest side. */
-#define VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_OBJ_CLOSE          58
+#define VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_OBJ_CLOSE          59
 /** Reads from an object on the guest side. */
-#define VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_OBJ_READ           59
+#define VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_OBJ_READ           60
 /** Writes to an object on the guest side. */
-#define VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_OBJ_WRITE          60
+#define VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_OBJ_WRITE          61
 /** Indicates that the host has canceled a transfer. */
-#define VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_CANCEL             61
+#define VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_CANCEL             62
 /** Indicates that the an unrecoverable error on the host occurred . */
-#define VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_ERROR              62
+#define VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_ERROR              63
 
 /*
@@ -129,34 +131,37 @@
  *  New since URI handling was implemented. */
 #define VBOX_SHARED_CLIPBOARD_GUEST_FN_REPLY             9
+/** Reports the available root entries of a transfer.
+  *  New since URI handling was implemented. */
+#define VBOX_SHARED_CLIPBOARD_GUEST_FN_ROOTS             10
 /** Opens / gets a list handle from the host.
  *  New since URI handling was implemented. */
-#define VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_OPEN         10
+#define VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_OPEN         11
 /** Closes a list handle from the host.
  *  New since URI handling was implemented. */
-#define VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_CLOSE        11
+#define VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_CLOSE        12
 /** Reads a list header from the host.
  *  New since URI handling was implemented. */
-#define VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_HDR_READ     12
+#define VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_HDR_READ     13
 /** Writes a list header to the host.
  *  New since URI handling was implemented. */
-#define VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_HDR_WRITE    13
+#define VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_HDR_WRITE    14
 /** New since URI handling was implemented. */
-#define VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_ENTRY_READ   14
+#define VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_ENTRY_READ   15
 /** New since URI handling was implemented. */
-#define VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_ENTRY_WRITE  15
+#define VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_ENTRY_WRITE  16
 /** New since URI handling was implemented. */
-#define VBOX_SHARED_CLIPBOARD_GUEST_FN_OBJ_OPEN          16
+#define VBOX_SHARED_CLIPBOARD_GUEST_FN_OBJ_OPEN          17
 /** New since URI handling was implemented. */
-#define VBOX_SHARED_CLIPBOARD_GUEST_FN_OBJ_CLOSE         17
+#define VBOX_SHARED_CLIPBOARD_GUEST_FN_OBJ_CLOSE         18
 /** New since URI handling was implemented. */
-#define VBOX_SHARED_CLIPBOARD_GUEST_FN_OBJ_READ          18
+#define VBOX_SHARED_CLIPBOARD_GUEST_FN_OBJ_READ          19
 /**  New since URI handling was implemented. */
-#define VBOX_SHARED_CLIPBOARD_GUEST_FN_OBJ_WRITE         19
+#define VBOX_SHARED_CLIPBOARD_GUEST_FN_OBJ_WRITE         20
 /** Reports cancellation of the current operation to the host.
  *  New since URI handling was implemented. */
-#define VBOX_SHARED_CLIPBOARD_GUEST_FN_CANCEL            20
+#define VBOX_SHARED_CLIPBOARD_GUEST_FN_CANCEL            21
 /** Reports an error to the host.
  *  New since URI handling was implemented. */
-#define VBOX_SHARED_CLIPBOARD_GUEST_FN_ERROR             21
+#define VBOX_SHARED_CLIPBOARD_GUEST_FN_ERROR             22
 
 /**
@@ -174,4 +179,5 @@
         RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_HOST_MSG_REPORT_FORMATS);
         RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_TRANSFER_START);
+        RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_ROOTS);
         RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_LIST_OPEN);
         RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_LIST_CLOSE);
@@ -208,4 +214,5 @@
         RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_GUEST_FN_STATUS);
         RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_GUEST_FN_REPLY);
+        RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_GUEST_FN_ROOTS);
         RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_OPEN);
         RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_CLOSE);
@@ -328,4 +335,5 @@
 #define VBOX_SHAREDCLIPBOARD_LISTHDR_FLAG_NONE       0
 
+/** No additional information provided. */
 #define VBOX_SHAREDCLIPBOARD_INFO_FLAG_NONE          0
 /** Get object information of type SHAREDCLIPBOARDFSOBJINFO. */
@@ -362,13 +370,13 @@
     VBGLIOCHGCMCALL hdr;
 
-    /** uint32_t, in: Context ID. Unused at the moment. */
-    HGCMFunctionParameter uContext;
-    /** uint32_t, in: Message type of type VBOX_SHAREDCLIPBOARD_REPLYMSGTYPE_XXX. */
+    /** uint32_t, out: Context ID. Unused at the moment. */
+    HGCMFunctionParameter uContext;
+    /** uint32_t, out: Message type of type VBOX_SHAREDCLIPBOARD_REPLYMSGTYPE_XXX. */
     HGCMFunctionParameter enmType;
-    /** uint32_t, in: IPRT result of overall operation. */
+    /** uint32_t, out: IPRT result of overall operation. */
     HGCMFunctionParameter rc;
-    /** uint32_t, in: Size of optional payload of this reply, based on the message type. */
+    /** uint32_t, out: Size of optional payload of this reply, based on the message type. */
     HGCMFunctionParameter cbPayload;
-    /** pointer, in: Optional payload of this reply, based on the message type. */
+    /** pointer, out: Optional payload of this reply, based on the message type. */
     HGCMFunctionParameter pvPayload;
     union
@@ -388,4 +396,28 @@
 
 /**
+ * Reads / Writes the roots list.
+ */
+typedef struct _VBoxClipboardRootsMsg
+{
+    VBGLIOCHGCMCALL hdr;
+
+    /** uint32_t, in: Context ID. Unused at the moment. */
+    HGCMFunctionParameter uContext;
+    /** uint32_t, in: Roots listing flags; unused at the moment. */
+    HGCMFunctionParameter fRoots;
+    /** uint32_t, out: Boolean indicating that more root items are following
+     *                 (via another message). */
+    HGCMFunctionParameter fMore;
+    /** uint32_t, out: Number of root items in this message. */
+    HGCMFunctionParameter cRoots;
+    /** uin32_t, out: Size (in bytes) of string list. */
+    HGCMFunctionParameter cbRoots;
+    /** pointer, out: string list (separated with \r\n) containing the root items. */
+    HGCMFunctionParameter pvRoots;
+} VBoxClipboardRootsMsg;
+
+#define VBOX_SHARED_CLIPBOARD_CPARMS_ROOTS 6
+
+/**
  * Opens a list.
  */
@@ -500,14 +532,16 @@
     VBGLIOCHGCMCALL hdr;
 
-    /** in: Request parameters. */
+    /** in/out: Request parameters. */
     VBoxClipboardListEntryReqParms ReqParms;
+    /** pointer, in/out: Entry name. */
+    HGCMFunctionParameter          szName;
     /** uint32_t, out: Bytes to be used for information/How many bytes were used.  */
     HGCMFunctionParameter          cbInfo;
-    /** pointer, out: Information to be set/get (SHAREDCLIPBOARDFSOBJINFO only currently).
+    /** pointer, in/out: Information to be set/get (SHAREDCLIPBOARDFSOBJINFO only currently).
      * Do not forget to set the SHAREDCLIPBOARDFSOBJINFO::Attr::enmAdditional for Get operation as well.  */
     HGCMFunctionParameter          pvInfo;
 } VBoxClipboardListEntryMsg;
 
-#define VBOX_SHARED_CLIPBOARD_CPARMS_LIST_ENTRY 5
+#define VBOX_SHARED_CLIPBOARD_CPARMS_LIST_ENTRY 6
 
 typedef struct _VBoxClipboardObjOpenMsg
Index: /trunk/include/VBox/VBoxGuestLib.h
===================================================================
--- /trunk/include/VBox/VBoxGuestLib.h	(revision 79671)
+++ /trunk/include/VBox/VBoxGuestLib.h	(revision 79672)
@@ -625,4 +625,7 @@
 
 VBGLR3DECL(int)     VbglR3ClipboardTransferSendStatus(HGCMCLIENTID idClient, SHAREDCLIPBOARDURITRANSFERSTATUS uStatus);
+
+VBGLR3DECL(int)     VbglR3ClipboardRootsRecv(HGCMCLIENTID idClient, uint32_t *pfRoots);
+VBGLR3DECL(int)     VbglR3ClipboardRootsWrite(HGCMCLIENTID idClient, uint32_t cRoots, const char *papszList, uint32_t cbList);
 
 VBGLR3DECL(int)     VbglR3ClipboardListOpenSend(HGCMCLIENTID idClient, PVBOXCLIPBOARDLISTOPENPARMS pOpenParms, PSHAREDCLIPBOARDLISTHANDLE phList);
Index: /trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxClipboard.cpp
===================================================================
--- /trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxClipboard.cpp	(revision 79671)
+++ /trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxClipboard.cpp	(revision 79672)
@@ -80,6 +80,4 @@
     PVBOXCLIPBOARDCONTEXT       pClipboardCtx;
     PSHAREDCLIPBOARDURITRANSFER pTransfer;
-    char                       *papszURIList;
-    uint32_t                    cbURIList;
 } VBOXCLIPBOARDURIWRITETHREADCTX, *PVBOXCLIPBOARDURIWRITETHREADCTX;
 #endif /* VBOX_WITH_SHARED_CLIPBOARD_URI_LIST */
@@ -156,7 +154,4 @@
         VbglR3ClipboardDisconnect(uClientID);
     }
-
-    if (pCtx->papszURIList)
-        RTStrFree(pCtx->papszURIList);
 
     RTMemFree(pCtx);
@@ -787,45 +782,24 @@
                if (RT_SUCCESS(rc))
                {
-            #if 0
-                   SHAREDCLIPBOARDURITRANSFERCALLBACKS TransferCallbacks;
-                   RT_ZERO(TransferCallbacks);
-
-                   TransferCallbacks.pvUser              = &pCtx->URI;
-                   TransferCallbacks.pfnTransferComplete = vboxClipboardURITransferCompleteCallback;
-                   TransferCallbacks.pfnTransferError    = vboxClipboardURITransferErrorCallback;
-
-                   SharedClipboardURITransferSetCallbacks(pTransfer, &TransferCallbacks);
-
-                   SHAREDCLIPBOARDPROVIDERCREATIONCTX creationCtx;
-                   RT_ZERO(creationCtx);
-                   creationCtx.enmSource = SHAREDCLIPBOARDSOURCE_LOCAL;
-
-                   RT_ZERO(creationCtx.Interface);
-                   creationCtx.Interface.pfnListHdrWrite   = vboxClipboardURIListHdrWrite;
-                   creationCtx.Interface.pfnListEntryWrite = vboxClipboardURIListEntryWrite;
-                   creationCtx.Interface.pfnObjOpen        = vboxClipboardURIObjOpen;
-                   creationCtx.Interface.pfnObjClose       = vboxClipboardURIObjClose;
-                   creationCtx.Interface.pfnObjWrite       = vboxClipboardURIObjWrite;
-
-                   creationCtx.pvUser = pCtx;
-
-                   rc = SharedClipboardURITransferSetInterface(pTransfer, &creationCtx);
+                   rc = SharedClipboardURICtxTransferAdd(&pCtx->URI, pTransfer);
                    if (RT_SUCCESS(rc))
                    {
-            #endif
-                       rc = SharedClipboardURICtxTransferAdd(&pCtx->URI, pTransfer);
-                       if (RT_SUCCESS(rc))
+                       /* The data data in CF_HDROP format, as the files are locally present and don't need to be
+                       * presented as a IDataObject or IStream. */
+                       HANDLE hClip = hClip = GetClipboardData(CF_HDROP);
+                       if (hClip)
                        {
-                           /* The data data in CF_HDROP format, as the files are locally present and don't need to be
-                           * presented as a IDataObject or IStream. */
-                           HANDLE hClip = hClip = GetClipboardData(CF_HDROP);
-                           if (hClip)
+                           HDROP hDrop = (HDROP)GlobalLock(hClip);
+                           if (hDrop)
                            {
-                               HDROP hDrop = (HDROP)GlobalLock(hClip);
-                               if (hDrop)
+                               char    *papszList;
+                               uint32_t cbList;
+                               rc = VBoxClipboardWinDropFilesToStringList((DROPFILES *)hDrop, &papszList, &cbList);
+
+                               GlobalUnlock(hClip);
+
+                               if (RT_SUCCESS(rc))
                                {
-                                   char    *papszList;
-                                   uint32_t cbList;
-                                   rc = VBoxClipboardWinDropFilesToStringList((DROPFILES *)hDrop, &papszList, &cbList);
+                                   rc = SharedClipboardURILTransferSetRoots(pTransfer, papszList, cbList);
                                    if (RT_SUCCESS(rc))
                                    {
@@ -836,36 +810,27 @@
                                            pThreadCtx->pClipboardCtx = pCtx;
                                            pThreadCtx->pTransfer     = pTransfer;
-                                           pThreadCtx->papszURIList  = papszList;
-                                           pThreadCtx->cbURIList     = cbList;
-
-                                           GlobalUnlock(hClip);
-
+
+                                           rc = SharedClipboardURITransferPrepare(pTransfer);
                                            if (RT_SUCCESS(rc))
                                            {
-                                               rc = SharedClipboardURITransferPrepare(pTransfer);
-                                               if (RT_SUCCESS(rc))
-                                               {
-                                                   rc = SharedClipboardURITransferRun(pTransfer, vboxClipboardURIWriteThread,
-                                                                                      pThreadCtx /* pvUser */);
-                                                   /* pThreadCtx now is owned by vboxClipboardURIWriteThread(). */
-                                               }
+                                               rc = SharedClipboardURITransferRun(pTransfer, vboxClipboardURIWriteThread,
+                                                                                  pThreadCtx /* pvUser */);
+                                               /* pThreadCtx now is owned by vboxClipboardURIWriteThread(). */
                                            }
                                        }
                                        else
                                            rc = VERR_NO_MEMORY;
-
-                                       if (RT_FAILURE(rc))
-                                       {
-                                           RTStrFree(papszList);
-                                       }
                                    }
-                               }
-                               else
-                               {
-                                   hClip = NULL;
+
+                                   if (papszList)
+                                       RTStrFree(papszList);
                                }
                            }
+                           else
+                           {
+                               hClip = NULL;
+                           }
                        }
-                   //}
+                   }
                }
 
Index: /trunk/src/VBox/Additions/common/VBoxGuest/lib/VBoxGuestR3LibClipboard.cpp
===================================================================
--- /trunk/src/VBox/Additions/common/VBoxGuest/lib/VBoxGuestR3LibClipboard.cpp	(revision 79671)
+++ /trunk/src/VBox/Additions/common/VBoxGuest/lib/VBoxGuestR3LibClipboard.cpp	(revision 79672)
@@ -278,4 +278,66 @@
 }
 
+VBGLR3DECL(int) VbglR3ClipboardRootsRecv(HGCMCLIENTID idClient, PVBOXCLIPBOARDROOTS pRoots)
+{
+    AssertPtrReturn(pRoots, VERR_INVALID_POINTER);
+
+    VBoxClipboardRootsMsg Msg;
+    RT_ZERO(Msg);
+
+    VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient,
+                       VBOX_SHARED_CLIPBOARD_GUEST_FN_MSG_GET, VBOX_SHARED_CLIPBOARD_CPARMS_ROOTS);
+
+    Msg.uContext.SetUInt32(VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_ROOTS);
+    Msg.fRoots.SetUInt32(0);
+    Msg.fMore.SetUInt32(0);
+    Msg.cRoots.SetUInt32(0);
+    Msg.cbRoots.SetUInt32(pRoots->cbRoots);
+    Msg.pvRoots.SetPtr((void *)pRoots->pszRoots, pRoots->cbRoots);
+
+    int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
+    if (RT_SUCCESS(rc))
+    {
+        uint32_t fMore;
+        rc = Msg.fMore.GetUInt32(&fMore); AssertRC(rc);
+        if (RT_SUCCESS(rc))
+        {
+            pRoots->fMore = RT_BOOL(fMore);
+        }
+        if (RT_SUCCESS(rc))
+            rc = Msg.fRoots.GetUInt32(&pRoots->fRoots); AssertRC(rc);
+        if (RT_SUCCESS(rc))
+            rc = Msg.cRoots.GetUInt32(&pRoots->cRoots); AssertRC(rc);
+        if (RT_SUCCESS(rc))
+            rc = Msg.cbRoots.GetUInt32(&pRoots->cbRoots); AssertRC(rc);
+    }
+
+    LogFlowFuncLeaveRC(rc);
+    return rc;
+}
+
+VBGLR3DECL(int) VbglR3ClipboardRootsWrite(HGCMCLIENTID idClient, uint32_t cRoots, char *papszList, uint32_t cbList)
+{
+    AssertPtrReturn(papszList, VERR_INVALID_POINTER);
+    AssertReturn(cbList,       VERR_INVALID_PARAMETER);
+
+    VBoxClipboardRootsMsg Msg;
+    RT_ZERO(Msg);
+
+    VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient,
+                       VBOX_SHARED_CLIPBOARD_GUEST_FN_ROOTS, VBOX_SHARED_CLIPBOARD_CPARMS_ROOTS);
+
+    Msg.uContext.SetUInt32(0); /** @todo Context ID not used yet. */
+    Msg.fRoots.SetUInt32(0);
+    Msg.fMore.SetUInt32(0);
+    Msg.cRoots.SetUInt32(cRoots);
+    Msg.cbRoots.SetUInt32(cbList);
+    Msg.pvRoots.SetPtr(papszList, cbList);
+
+    int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
+
+    LogFlowFuncLeaveRC(rc);
+    return rc;
+}
+
 VBGLR3DECL(int) VbglR3ClipboardListOpenSend(HGCMCLIENTID idClient, PVBOXCLIPBOARDLISTOPENPARMS pOpenParms,
                                             PSHAREDCLIPBOARDLISTHANDLE phList)
@@ -512,4 +574,5 @@
     Msg.ReqParms.fInfo.SetUInt32(0);
 
+    Msg.szName.SetPtr(pListEntry->pszName, pListEntry->cbName);
     Msg.cbInfo.SetUInt32(0);
     Msg.pvInfo.SetPtr(pListEntry->pvInfo, pListEntry->cbInfo);
@@ -567,4 +630,5 @@
     Msg.ReqParms.fInfo.SetUInt32(pListEntry->fInfo);
 
+    Msg.szName.SetPtr(pListEntry->pszName, pListEntry->cbName);
     Msg.cbInfo.SetUInt32(pListEntry->cbInfo);
     Msg.pvInfo.SetPtr(pListEntry->pvInfo, pListEntry->cbInfo);
@@ -596,4 +660,33 @@
         {
 #ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
+            case VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_ROOTS:
+            {
+                LogFlowFunc(("VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_ROOTS\n"));
+
+                VBOXCLIPBOARDROOTS Roots;
+                rc = SharedClipboardURIRootsInit(&Roots);
+                if (RT_SUCCESS(rc))
+                {
+                    rc = VbglR3ClipboardRootsRecv(idClient, &Roots);
+                    if (RT_SUCCESS(rc))
+                    {
+                        /** @todo Handle fFlags. */
+
+                        char    *pszRoots = NULL;
+                        uint32_t cRoots   = 0;
+                        rc = SharedClipboardURILTransferGetRoots(pTransfer, &pszRoots, &cRoots);
+                        if (RT_SUCCESS(rc))
+                        {
+                            /** @todo Split up transfers in _64K each. */
+
+                            rc = VbglR3ClipboardRootsWrite(idClient, cRoots,
+                                                           pszRoots, pszRoots ? (uint32_t)strlen(pszRoots) : NULL);
+                        }
+                    }
+                }
+
+                break;
+            }
+
             case VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_LIST_OPEN:
             {
@@ -607,4 +700,6 @@
                     if (RT_SUCCESS(rc))
                     {
+                        LogFlowFunc(("pszPath=%s\n", openParmsList.pszPath));
+
                         SHAREDCLIPBOARDLISTHANDLE hList = SHAREDCLIPBOARDLISTHANDLE_INVALID;
                         rc = SharedClipboardURITransferListOpen(pTransfer, &openParmsList, &hList);
@@ -613,8 +708,9 @@
                         int rc2 = VbglR3ClipboardListOpenReply(idClient, rc, hList);
                         AssertRC(rc2);
+
+                        SharedClipboardURIListOpenParmsDestroy(&openParmsList);
                     }
-
-                    SharedClipboardURIListOpenParmsDestroy(&openParmsList);
                 }
+
                 break;
             }
@@ -676,6 +772,6 @@
                 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_LIST_ENTRY_READ\n"));
 
-                VBOXCLIPBOARDLISTENTRY listEntry;
-                rc = SharedClipboardURIListEntryInit(&listEntry);
+                VBOXCLIPBOARDLISTENTRY entryList;
+                rc = SharedClipboardURIListEntryInit(&entryList);
                 if (RT_SUCCESS(rc))
                 {
@@ -685,12 +781,17 @@
                     if (RT_SUCCESS(rc))
                     {
-                        rc = SharedClipboardURITransferListRead(pTransfer, hList, &listEntry);
+                        rc = SharedClipboardURITransferListRead(pTransfer, hList, &entryList);
                         if (RT_SUCCESS(rc))
                         {
-                            rc = VbglR3ClipboardListEntryWrite(idClient, hList, &listEntry);
+                            PSHAREDCLIPBOARDFSOBJINFO pObjInfo = (PSHAREDCLIPBOARDFSOBJINFO)entryList.pvInfo;
+                            Assert(entryList.cbInfo == sizeof(SHAREDCLIPBOARDFSOBJINFO));
+
+                            LogFlowFunc(("\t%s (%RU64 bytes)\n", entryList.pszName, pObjInfo->cbObject));
+
+                            rc = VbglR3ClipboardListEntryWrite(idClient, hList, &entryList);
                         }
                     }
 
-                    SharedClipboardURIListEntryDestroy(&listEntry);
+                    SharedClipboardURIListEntryDestroy(&entryList);
                 }
 
Index: /trunk/src/VBox/GuestHost/SharedClipboard/ClipboardDataObjectImpl-win.cpp
===================================================================
--- /trunk/src/VBox/GuestHost/SharedClipboard/ClipboardDataObjectImpl-win.cpp	(revision 79671)
+++ /trunk/src/VBox/GuestHost/SharedClipboard/ClipboardDataObjectImpl-win.cpp	(revision 79672)
@@ -246,59 +246,92 @@
     RTThreadUserSignal(RTThreadSelf());
 
+    LogRel2(("Shared Clipboard: Calculating transfer ....\n"));
+
     int rc = SharedClipboardURITransferOpen(pTransfer);
     if (RT_SUCCESS(rc))
     {
-        VBOXCLIPBOARDLISTOPENPARMS openParmsList;
-        rc = SharedClipboardURIListOpenParmsInit(&openParmsList);
+        uint32_t cRoots;
+        char    *pszRoots;
+        rc = SharedClipboardURILTransferGetRoots(pTransfer, &pszRoots, &cRoots);
         if (RT_SUCCESS(rc))
         {
-            SHAREDCLIPBOARDLISTHANDLE hList;
-            rc = SharedClipboardURITransferListOpen(pTransfer, &openParmsList, &hList);
+            SharedClipboardURIListRootEntries lstRoots = RTCString(pszRoots, strlen(pszRoots)).split("\r\n");
+            Assert(lstRoots.size() == cRoots);
+
+            LogFlowFunc(("cRoots=%zu\n", lstRoots.size()));
+
+            for (uint32_t i = 0; i < lstRoots.size(); i++)
+            {
+                VBOXCLIPBOARDLISTOPENPARMS openParmsList;
+                rc = SharedClipboardURIListOpenParmsInit(&openParmsList);
+                if (RT_SUCCESS(rc))
+                {
+                    LogFlowFunc(("pszRoot=%s\n", lstRoots[i].c_str()));
+
+                    rc = RTStrCopy(openParmsList.pszPath, openParmsList.cbPath, lstRoots[i].c_str());
+                    if (RT_FAILURE(rc))
+                        break;
+
+                    SHAREDCLIPBOARDLISTHANDLE hList;
+                    rc = SharedClipboardURITransferListOpen(pTransfer, &openParmsList, &hList);
+                    if (RT_SUCCESS(rc))
+                    {
+                        LogFlowFunc(("hList=%RU64\n", hList));
+
+                        VBOXCLIPBOARDLISTHDR hdrList;
+                        rc = SharedClipboardURITransferListGetHeader(pTransfer, hList, &hdrList);
+                        if (RT_SUCCESS(rc))
+                        {
+                            LogFlowFunc(("cTotalObjects=%RU64, cbTotalSize=%RU64\n\n",
+                                         hdrList.cTotalObjects, hdrList.cbTotalSize));
+
+                            for (uint64_t i = 0; i < hdrList.cTotalObjects; i++)
+                            {
+                                VBOXCLIPBOARDLISTENTRY entryList;
+                                rc = SharedClipboardURITransferListRead(pTransfer, hList, &entryList);
+                                if (RT_SUCCESS(rc))
+                                {
+                                    PSHAREDCLIPBOARDFSOBJINFO pObjInfo = (PSHAREDCLIPBOARDFSOBJINFO)entryList.pvInfo;
+                                    Assert(entryList.cbInfo == sizeof(SHAREDCLIPBOARDFSOBJINFO));
+
+                                    LogFlowFunc(("\t%s (%RU64 bytes)\n", entryList.pszName, pObjInfo->cbObject));
+                                }
+                                else
+                                    break;
+
+                                if (pTransfer->Thread.fStop)
+                                    break;
+                            }
+                        }
+
+                        SharedClipboardURITransferListClose(pTransfer, hList);
+                    }
+
+                    SharedClipboardURIListOpenParmsDestroy(&openParmsList);
+                }
+
+                if (RT_FAILURE(rc))
+                    break;
+            }
+
             if (RT_SUCCESS(rc))
             {
-                LogFlowFunc(("hList=%RU64\n", hList));
-
-                VBOXCLIPBOARDLISTHDR hdrList;
-                rc = SharedClipboardURITransferListGetHeader(pTransfer, hList, &hdrList);
-                if (RT_SUCCESS(rc))
-                {
-                    LogFlowFunc(("cTotalObjects=%RU64, cbTotalSize=%RU64\n\n",
-                                 hdrList.cTotalObjects, hdrList.cbTotalSize));
-
-                    for (uint64_t i = 0; i < hdrList.cTotalObjects; i++)
-                    {
-                        VBOXCLIPBOARDLISTENTRY entryList;
-                        rc = SharedClipboardURITransferListRead(pTransfer, hList, &entryList);
-                        if (RT_SUCCESS(rc))
-                        {
-                        }
-                        else
-                            break;
-
-                        if (pTransfer->Thread.fStop)
-                            break;
-                    }
-
-                    if (RT_SUCCESS(rc))
-                    {
-                        /*
-                         * Signal the "list complete" event so that this data object can return (valid) data via ::GetData().
-                         * This in turn then will create IStream instances (by the OS) for each file system object to handle.
-                         */
-                        int rc2 = RTSemEventSignal(pThis->m_EventListComplete);
-                        AssertRC(rc2);
-
-                        LogFlowFunc(("Waiting for transfer to complete ...\n"));
-
-                        /* Transferring stuff can take a while, so don't use any timeout here. */
-                        rc2 = RTSemEventWait(pThis->m_EventTransferComplete, RT_INDEFINITE_WAIT);
-                        AssertRC(rc2);
-                    }
-                }
-
-                SharedClipboardURITransferListClose(pTransfer, hList);
+                LogRel2(("Shared Clipboard: Calculation complete, starting transfer ...\n"));
+
+                /*
+                 * Signal the "list complete" event so that this data object can return (valid) data via ::GetData().
+                 * This in turn then will create IStream instances (by the OS) for each file system object to handle.
+                 */
+                int rc2 = RTSemEventSignal(pThis->m_EventListComplete);
+                AssertRC(rc2);
+
+                LogFlowFunc(("Waiting for transfer to complete ...\n"));
+
+                /* Transferring stuff can take a while, so don't use any timeout here. */
+                rc2 = RTSemEventWait(pThis->m_EventTransferComplete, RT_INDEFINITE_WAIT);
+                AssertRC(rc2);
             }
 
-            SharedClipboardURIListOpenParmsDestroy(&openParmsList);
+            RTStrFree(pszRoots);
         }
 
Index: /trunk/src/VBox/GuestHost/SharedClipboard/clipboard-uri.cpp
===================================================================
--- /trunk/src/VBox/GuestHost/SharedClipboard/clipboard-uri.cpp	(revision 79671)
+++ /trunk/src/VBox/GuestHost/SharedClipboard/clipboard-uri.cpp	(revision 79672)
@@ -37,4 +37,61 @@
 
 
+int SharedClipboardURIRootsInit(PVBOXCLIPBOARDROOTS pRoots)
+{
+    AssertPtrReturn(pRoots, VERR_INVALID_POINTER);
+
+    RT_BZERO(pRoots, sizeof(VBOXCLIPBOARDROOTS));
+
+    const uint32_t cbRoots = _64K;
+
+    pRoots->pszRoots = RTStrAlloc(cbRoots);
+    if (!pRoots->pszRoots)
+        return VERR_NO_MEMORY;
+
+    pRoots->cbRoots = cbRoots;
+
+    return VINF_SUCCESS;
+}
+
+void SharedClipboardURIRootsDestroy(PVBOXCLIPBOARDROOTS pRoots)
+{
+    if (!pRoots)
+        return;
+
+    if (pRoots->pszRoots)
+        RTStrFree(pRoots->pszRoots);
+}
+
+PVBOXCLIPBOARDROOTS SharedClipboardURIRootsDup(PVBOXCLIPBOARDROOTS pRoots)
+{
+    AssertPtrReturn(pRoots, NULL);
+
+    int rc = VINF_SUCCESS;
+
+    PVBOXCLIPBOARDROOTS pRootsDup = (PVBOXCLIPBOARDROOTS)RTMemAlloc(sizeof(VBOXCLIPBOARDROOTS));
+    if (pRootsDup)
+    {
+        *pRootsDup = *pRoots;
+
+        if (pRoots->pszRoots)
+        {
+            pRootsDup->pszRoots = RTStrDup(pRoots->pszRoots);
+            if (!pRootsDup->pszRoots)
+                rc = VERR_NO_MEMORY;
+        }
+    }
+
+    if (RT_FAILURE(rc))
+    {
+        if (pRootsDup->pszRoots)
+            RTStrFree(pRootsDup->pszRoots);
+
+        RTMemFree(pRootsDup);
+        pRootsDup = NULL;
+    }
+
+    return pRootsDup;
+}
+
 /**
  * Allocates a VBOXCLIPBOARDListHdr structure.
@@ -287,5 +344,13 @@
     *pDst = *pSrc;
 
-    if (pSrc->pvInfo)
+    if (pSrc->pszName)
+    {
+        pDst->pszName = RTStrDup(pSrc->pszName);
+        if (!pDst->pszName)
+            rc = VERR_NO_MEMORY;
+    }
+
+    if (   RT_SUCCESS(rc)
+        && pSrc->pvInfo)
     {
         pDst->pvInfo = RTMemDup(pSrc->pvInfo, pSrc->cbInfo);
@@ -341,5 +406,6 @@
  * Initializes a clipboard list entry structure.
  *
- * @param   pListEntry          clipboard list entry structure to initialize.
+ * @returns VBox status code.
+ * @param   pListEntry          Clipboard list entry structure to initialize.
  */
 int SharedClipboardURIListEntryInit(PVBOXCLIPBOARDLISTENTRY pListEntry)
@@ -347,4 +413,10 @@
     RT_BZERO(pListEntry, sizeof(VBOXCLIPBOARDLISTENTRY));
 
+    pListEntry->pszName = RTStrAlloc(VBOXCLIPBOARDLISTENTRY_MAX_NAME);
+    if (!pListEntry->pszName)
+        return VERR_NO_MEMORY;
+
+    pListEntry->cbName = VBOXCLIPBOARDLISTENTRY_MAX_NAME;
+
     return VINF_SUCCESS;
 }
@@ -353,5 +425,5 @@
  * Initializes a clipboard list entry structure.
  *
- * @param   pListEntry          clipboard list entry structure to destroy.
+ * @param   pListEntry          Clipboard list entry structure to destroy.
  */
 void SharedClipboardURIListEntryDestroy(PVBOXCLIPBOARDLISTENTRY pListEntry)
@@ -359,4 +431,12 @@
     if (!pListEntry)
         return;
+
+    if (pListEntry->pszName)
+    {
+        RTStrFree(pListEntry->pszName);
+
+        pListEntry->pszName = NULL;
+        pListEntry->cbName  = 0;
+    }
 
     if (pListEntry->pvInfo)
@@ -382,270 +462,4 @@
     return true; /** @todo Implement this. */
 }
-
-#if 0
-/**
- * Creates (allocates) and initializes a VBOXCLIPBOARDDIRDATA structure.
- *
- * @param   ppDirData           Where to return the created VBOXCLIPBOARDDIRDATA structure on success.
- */
-int SharedClipboardURIDirDataAlloc(PVBOXCLIPBOARDDIRDATA *ppDirData)
-{
-    PVBOXCLIPBOARDDIRDATA pDirData = (PVBOXCLIPBOARDDIRDATA)RTMemAlloc(sizeof(VBOXCLIPBOARDDIRDATA));
-    if (!pDirData)
-        return VERR_NO_MEMORY;
-
-    int rc = SharedClipboardURIDirDataInit(pDirData);
-    if (RT_SUCCESS(rc))
-        *ppDirData = pDirData;
-
-    return rc;
-}
-
-/**
- * Frees a VBOXCLIPBOARDDIRDATA structure.
- *
- * @param   pDirData           Where to return the created VBOXCLIPBOARDDIRDATA structure on success.
- */
-void SharedClipboardURIDirDataFree(PVBOXCLIPBOARDDIRDATA pDirData)
-{
-    if (!pDirData)
-        return;
-
-    SharedClipboardURIDirDataDestroy(pDirData);
-    RTMemFree(pDirData);
-}
-
-/**
- * Initializes a VBOXCLIPBOARDDIRDATA structure.
- *
- * @param   pDirData            VBOXCLIPBOARDDIRDATA structure to initialize.
- */
-int SharedClipboardURIDirDataInit(PVBOXCLIPBOARDDIRDATA pDirData)
-{
-    RT_BZERO(pDirData, sizeof(VBOXCLIPBOARDDIRDATA));
-
-    return VINF_SUCCESS;
-}
-
-/**
- * Destroys a VBOXCLIPBOARDDIRDATA structure.
- *
- * @param   pDirData            VBOXCLIPBOARDDIRDATA structure to destroy.
- */
-void SharedClipboardURIDirDataDestroy(PVBOXCLIPBOARDDIRDATA pDirData)
-{
-    if (!pDirData)
-        return;
-
-    if (pDirData->pszPath)
-    {
-        Assert(pDirData->cbPath);
-        RTStrFree(pDirData->pszPath);
-        pDirData->pszPath = NULL;
-    }
-}
-
-/**
- * Duplicates (allocates) a VBOXCLIPBOARDDIRDATA structure.
- *
- * @returns Duplicated VBOXCLIPBOARDDIRDATA structure on success.
- * @param   pDirData            VBOXCLIPBOARDDIRDATA to duplicate.
- */
-PVBOXCLIPBOARDDIRDATA SharedClipboardURIDirDataDup(PVBOXCLIPBOARDDIRDATA pDirData)
-{
-    AssertPtrReturn(pDirData, NULL);
-
-    PVBOXCLIPBOARDDIRDATA pDirDataDup = (PVBOXCLIPBOARDDIRDATA)RTMemAllocZ(sizeof(VBOXCLIPBOARDDIRDATA));
-    if (pDirDataDup)
-    {
-        *pDirDataDup = *pDirData;
-
-        if (pDirData->pszPath)
-        {
-            pDirDataDup->pszPath = RTStrDup(pDirData->pszPath);
-            if (pDirDataDup->pszPath)
-                pDirDataDup->cbPath = pDirData->cbPath;
-        }
-    }
-
-    return pDirDataDup;
-}
-
-/**
- * Returns whether given clipboard directory data is valid or not.
- *
- * @returns \c true if valid, \c false if not.
- * @param   pDirData            Clipboard directory data to validate.
- */
-bool SharedClipboardURIDirDataIsValid(PVBOXCLIPBOARDDIRDATA pDirData)
-{
-    if (   !pDirData->cbPath
-        || pDirData->cbPath > RTPATH_MAX)
-        return false;
-
-    if (!RTStrIsValidEncoding(pDirData->pszPath))
-        return false;
-
-    return true;
-}
-
-/**
- * Initializes a VBOXCLIPBOARDFILEHDR structure.
- *
- * @param   pDirData            VBOXCLIPBOARDFILEHDR structure to initialize.
- */
-int SharedClipboardURIFileHdrInit(PVBOXCLIPBOARDFILEHDR pFileHdr)
-{
-    RT_BZERO(pFileHdr, sizeof(VBOXCLIPBOARDFILEHDR));
-
-    return VINF_SUCCESS;
-}
-
-/**
- * Destroys a VBOXCLIPBOARDFILEHDR structure.
- *
- * @param   pFileHdr            VBOXCLIPBOARDFILEHDR structure to destroy.
- */
-void SharedClipboardURIFileHdrDestroy(PVBOXCLIPBOARDFILEHDR pFileHdr)
-{
-    if (!pFileHdr)
-        return;
-
-    if (pFileHdr->pszFilePath)
-    {
-        Assert(pFileHdr->pszFilePath);
-        RTStrFree(pFileHdr->pszFilePath);
-        pFileHdr->pszFilePath = NULL;
-    }
-}
-
-/**
- * Frees a VBOXCLIPBOARDFILEHDR structure.
- *
- * @param   pFileHdr            VBOXCLIPBOARDFILEHDR structure to free.
- */
-void SharedClipboardURIFileHdrFree(PVBOXCLIPBOARDFILEHDR pFileHdr)
-{
-    if (!pFileHdr)
-        return;
-
-    SharedClipboardURIFileHdrDestroy(pFileHdr);
-
-    RTMemFree(pFileHdr);
-    pFileHdr = NULL;
-}
-
-/**
- * Duplicates (allocates) a VBOXCLIPBOARDFILEHDR structure.
- *
- * @returns Duplicated VBOXCLIPBOARDFILEHDR structure on success.
- * @param   pFileHdr            VBOXCLIPBOARDFILEHDR to duplicate.
- */
-PVBOXCLIPBOARDFILEHDR SharedClipboardURIFileHdrDup(PVBOXCLIPBOARDFILEHDR pFileHdr)
-{
-    AssertPtrReturn(pFileHdr, NULL);
-
-    PVBOXCLIPBOARDFILEHDR pFileHdrDup = (PVBOXCLIPBOARDFILEHDR)RTMemAllocZ(sizeof(VBOXCLIPBOARDFILEHDR));
-    if (pFileHdrDup)
-    {
-        *pFileHdrDup = *pFileHdr;
-
-        if (pFileHdr->pszFilePath)
-        {
-            pFileHdrDup->pszFilePath = RTStrDup(pFileHdr->pszFilePath);
-            if (pFileHdrDup->pszFilePath)
-                pFileHdrDup->cbFilePath = pFileHdrDup->cbFilePath;
-        }
-    }
-
-    return pFileHdrDup;
-}
-
-/**
- * Returns whether a given clipboard file header is valid or not.
- *
- * @returns \c true if valid, \c false if not.
- * @param   pFileHdr            Clipboard file header to validate.
- * @param   pListHdr            Data header to use for validation.
- */
-bool SharedClipboardURIFileHdrIsValid(PVBOXCLIPBOARDFILEHDR pFileHdr, PVBOXCLIPBOARDLISTHDR pListHdr)
-{
-    if (   !pFileHdr->cbFilePath
-        || pFileHdr->cbFilePath > RTPATH_MAX)
-        return false;
-
-    if (!RTStrIsValidEncoding(pFileHdr->pszFilePath))
-        return false;
-
-    if (pFileHdr->cbSize > pListHdr->cbTotalSize)
-        return false;
-
-    return true;
-}
-
-/**
- * Destroys a VBOXCLIPBOARDFILEDATA structure.
- *
- * @param   pFileData           VBOXCLIPBOARDFILEDATA structure to destroy.
- */
-void SharedClipboardURIFileDataDestroy(PVBOXCLIPBOARDFILEDATA pFileData)
-{
-    if (!pFileData)
-        return;
-
-    if (pFileData->pvData)
-    {
-        Assert(pFileData->cbData);
-        RTMemFree(pFileData->pvData);
-        pFileData->pvData = NULL;
-    }
-}
-
-/**
- * Duplicates (allocates) a VBOXCLIPBOARDFILEDATA structure.
- *
- * @returns Duplicated VBOXCLIPBOARDFILEDATA structure on success.
- * @param   pFileData           VBOXCLIPBOARDFILEDATA to duplicate.
- */
-PVBOXCLIPBOARDFILEDATA SharedClipboardURIFileDataDup(PVBOXCLIPBOARDFILEDATA pFileData)
-{
-    AssertPtrReturn(pFileData, NULL);
-
-    PVBOXCLIPBOARDFILEDATA pFileDataDup = (PVBOXCLIPBOARDFILEDATA)RTMemAllocZ(sizeof(VBOXCLIPBOARDFILEDATA));
-    if (pFileDataDup)
-    {
-        *pFileDataDup = *pFileData;
-
-        if (pFileData->pvData)
-        {
-            pFileDataDup->pvData = RTMemDup(pFileData->pvData, pFileData->cbData);
-            if (pFileDataDup->pvData)
-                pFileDataDup->cbData = pFileDataDup->cbData;
-        }
-
-        if (pFileData->pvChecksum)
-        {
-            pFileDataDup->pvChecksum = RTMemDup(pFileData->pvChecksum, pFileData->cbChecksum);
-            if (pFileDataDup->pvChecksum)
-                pFileDataDup->cbChecksum = pFileData->cbChecksum;
-        }
-    }
-
-    return pFileDataDup;
-}
-
-/**
- * Returns whether given clipboard file data is valid or not.
- *
- * @returns \c true if valid, \c false if not.
- * @param   pFileData           Clipboard file data to validate.
- * @param   pListHdr            Data header to use for validation.
- */
-bool SharedClipboardURIFileDataIsValid(PVBOXCLIPBOARDFILEDATA pFileData, PVBOXCLIPBOARDLISTHDR pListHdr)
-{
-    RT_NOREF(pFileData, pListHdr);
-    return true;
-}
-#endif
 
 /**
@@ -806,4 +620,10 @@
 }
 
+/**
+ * Creates a new list handle (local only).
+ *
+ * @returns New List handle on success, or SHAREDCLIPBOARDLISTHANDLE_INVALID on error.
+ * @param   pTransfer           URI clipboard transfer to create new list handle for.
+ */
 static SHAREDCLIPBOARDLISTHANDLE sharedClipboardURITransferListHandleNew(PSHAREDCLIPBOARDURITRANSFER pTransfer)
 {
@@ -813,4 +633,12 @@
 }
 
+/**
+ * Opens a list.
+ *
+ * @returns VBox status code.
+ * @param   pTransfer           URI clipboard transfer to handle.
+ * @param   pOpenParms          List open parameters to use for opening.
+ * @param   phList              Where to store the List handle of opened list on success.
+ */
 int SharedClipboardURITransferListOpen(PSHAREDCLIPBOARDURITRANSFER pTransfer, PVBOXCLIPBOARDLISTOPENPARMS pOpenParms,
                                        PSHAREDCLIPBOARDLISTHANDLE phList)
@@ -830,8 +658,4 @@
         if (pInfo)
         {
-            if (   !pOpenParms->pszPath
-                || !strlen(pOpenParms->pszPath))
-                RTStrAPrintf(&pOpenParms->pszPath, "C:\\Temp"); /** @todo FIX !!!! */
-
             RTFSOBJINFO objInfo;
             rc = RTPathQueryInfo(pOpenParms->pszPath, &objInfo, RTFSOBJATTRADD_NOTHING);
@@ -842,5 +666,6 @@
             else if (RTFS_IS_FILE(objInfo.Attr.fMode))
             {
-                rc = RTFileOpen(&pInfo->u.Local.hFile, pOpenParms->pszPath, RTFILE_O_READ | RTFILE_O_DENY_WRITE);
+                rc = RTFileOpen(&pInfo->u.Local.hFile, pOpenParms->pszPath,
+                                RTFILE_O_OPEN | RTFILE_O_READ | RTFILE_O_DENY_WRITE);
             }
             else if (RTFS_IS_SYMLINK(objInfo.Attr.fMode))
@@ -902,4 +727,11 @@
 }
 
+/**
+ * Closes a list.
+ *
+ * @returns VBox status code.
+ * @param   pTransfer           URI clipboard transfer to handle.
+ * @param   hList               Handle of list to close.
+ */
 int SharedClipboardURITransferListClose(PSHAREDCLIPBOARDURITRANSFER pTransfer, SHAREDCLIPBOARDLISTHANDLE hList)
 {
@@ -943,4 +775,11 @@
 }
 
+/**
+ * Adds a file to a list heaer.
+ *
+ * @returns VBox status code.
+ * @param   pHdr                List header to add file to.
+ * @param   pszPath             Path of file to add.
+ */
 static int sharedClipboardURITransferListHdrAddFile(PVBOXCLIPBOARDLISTHDR pHdr, const char *pszPath)
 {
@@ -957,4 +796,14 @@
 }
 
+/**
+ * Builds a list header, internal version.
+ *
+ * @returns VBox status code.
+ * @param   pHdr                Where to store the build list header.
+ * @param   pcszSrcPath         Source path of list.
+ * @param   pcszDstPath         Destination path of list.
+ * @param   pcszDstBase         Destination base path.
+ * @param   cchDstBase          Number of charaters of destination base path.
+ */
 static int sharedClipboardURITransferListHdrFromDir(PVBOXCLIPBOARDLISTHDR pHdr,
                                                     const char *pcszSrcPath, const char *pcszDstPath,
@@ -1067,4 +916,12 @@
 }
 
+/**
+ * Retrieves the header of a Shared Clipboard list.
+ *
+ * @returns VBox status code.
+ * @param   pTransfer           URI clipboard transfer to handle.
+ * @param   hList               Handle of list to get header for.
+ * @param   pHdr                Where to store the returned list header information.
+ */
 int SharedClipboardURITransferListGetHeader(PSHAREDCLIPBOARDURITRANSFER pTransfer, SHAREDCLIPBOARDLISTHANDLE hList,
                                             PVBOXCLIPBOARDLISTHDR pHdr)
@@ -1174,4 +1031,12 @@
 }
 
+/**
+ * Reads a single Shared Clipboard list entry.
+ *
+ * @returns VBox status code.
+ * @param   pTransfer           URI clipboard transfer to handle.
+ * @param   hList               List handle of list to read from.
+ * @param   pEntry              Where to store the read information.
+ */
 int SharedClipboardURITransferListRead(PSHAREDCLIPBOARDURITRANSFER pTransfer, SHAREDCLIPBOARDLISTHANDLE hList,
                                        PVBOXCLIPBOARDLISTENTRY pEntry)
@@ -1192,52 +1057,75 @@
             AssertPtr(pInfo);
 
+            LogFlowFunc(("\tfMode=%RU32, pszPath=%s\n", pInfo->fMode, pInfo->OpenParms.pszPath));
+
             if (RTFS_IS_DIRECTORY(pInfo->fMode))
             {
-                size_t        cbDirEntry = 0;
-                PRTDIRENTRYEX pDirEntry  = NULL;
-                rc = RTDirReadExA(pInfo->u.Local.hDirRoot, &pDirEntry, &cbDirEntry, RTFSOBJATTRADD_NOTHING, RTPATH_F_ON_LINK);
-                if (RT_SUCCESS(rc))
+                for (;;)
                 {
-                    switch (pDirEntry->Info.Attr.fMode & RTFS_TYPE_MASK)
+                    bool fSkipEntry = false; /* Whether to skip an entry in the enumeration. */
+
+                    size_t        cbDirEntry = 0;
+                    PRTDIRENTRYEX pDirEntry  = NULL;
+                    rc = RTDirReadExA(pInfo->u.Local.hDirRoot, &pDirEntry, &cbDirEntry, RTFSOBJATTRADD_NOTHING, RTPATH_F_ON_LINK);
+                    if (RT_SUCCESS(rc))
                     {
-                        case RTFS_TYPE_DIRECTORY:
+                        switch (pDirEntry->Info.Attr.fMode & RTFS_TYPE_MASK)
                         {
-                            /* Skip "." and ".." entries. */
-                            if (RTDirEntryExIsStdDotLink(pDirEntry))
+                            case RTFS_TYPE_DIRECTORY:
+                            {
+                                LogFlowFunc(("Directory: %s\n", pDirEntry->szName));
+
+                                /* Skip "." and ".." entries. */
+                                if (RTDirEntryExIsStdDotLink(pDirEntry))
+                                    fSkipEntry = true;
+
+                                RT_FALL_THROUGH();
+                            }
+
+                            case RTFS_TYPE_FILE:
+                            {
+                                LogFlowFunc(("File: %s\n", pDirEntry->szName));
+
+                                pEntry->pvInfo = (PSHAREDCLIPBOARDFSOBJINFO)RTMemAlloc(sizeof(SHAREDCLIPBOARDFSOBJINFO));
+                                if (pEntry->pvInfo)
+                                {
+                                    rc = RTStrCopy(pEntry->pszName, pEntry->cbName, pDirEntry->szName);
+                                    if (RT_SUCCESS(rc))
+                                    {
+                                        SharedClipboardFsObjFromIPRT(PSHAREDCLIPBOARDFSOBJINFO(pEntry->pvInfo), &pDirEntry->Info);
+
+                                        pEntry->cbInfo = sizeof(SHAREDCLIPBOARDFSOBJINFO);
+                                        pEntry->fInfo  = VBOX_SHAREDCLIPBOARD_INFO_FLAG_FSOBJINFO;
+                                    }
+                                }
+                                else
+                                    rc = VERR_NO_MEMORY;
                                 break;
-
-                            RT_FALL_THROUGH();
+                            }
+
+                            case RTFS_TYPE_SYMLINK:
+                            {
+                                /** @todo Not implemented yet. */
+                                break;
+                            }
+
+                            default:
+                                break;
                         }
 
-                        case RTFS_TYPE_FILE:
-                        {
-                            pEntry->pvInfo = (PSHAREDCLIPBOARDFSOBJINFO)RTMemAlloc(sizeof(SHAREDCLIPBOARDFSOBJINFO));
-                            if (pEntry->pvInfo)
-                            {
-                                SharedClipboardFsObjFromIPRT(PSHAREDCLIPBOARDFSOBJINFO(pEntry->pvInfo), &pDirEntry->Info);
-
-                                pEntry->cbInfo = sizeof(SHAREDCLIPBOARDFSOBJINFO);
-                                pEntry->fInfo  = 0; /** @todo Implement. */
-                            }
-                            else
-                                rc = VERR_NO_MEMORY;
-                            break;
-                        }
-
-                        case RTFS_TYPE_SYMLINK:
-                        {
-                            /** @todo Not implemented yet. */
-                            break;
-                        }
-
-                        default:
-                            break;
+                        RTDirReadExAFree(&pDirEntry, &cbDirEntry);
                     }
 
-                    RTDirReadExAFree(&pDirEntry, &cbDirEntry);
+                    if (   !fSkipEntry /* Do we have a valid entry? Bail out. */
+                        || RT_FAILURE(rc))
+                    {
+                        break;
+                    }
                 }
             }
             else if (RTFS_IS_FILE(pInfo->fMode))
             {
+                LogFlowFunc(("\tSingle file: %s\n", pInfo->OpenParms.pszPath));
+
                 RTFSOBJINFO objInfo;
                 rc = RTFileQueryInfo(pInfo->u.Local.hFile, &objInfo, RTFSOBJATTRADD_NOTHING);
@@ -1247,8 +1135,12 @@
                     if (pEntry->pvInfo)
                     {
-                        SharedClipboardFsObjFromIPRT(PSHAREDCLIPBOARDFSOBJINFO(pEntry->pvInfo), &objInfo);
-
-                        pEntry->cbInfo = sizeof(SHAREDCLIPBOARDFSOBJINFO);
-                        pEntry->fInfo  = 0; /** @todo Implement. */
+                        rc = RTStrCopy(pEntry->pszName, pEntry->cbName, pInfo->OpenParms.pszPath);
+                        if (RT_SUCCESS(rc))
+                        {
+                            SharedClipboardFsObjFromIPRT(PSHAREDCLIPBOARDFSOBJINFO(pEntry->pvInfo), &objInfo);
+
+                            pEntry->cbInfo = sizeof(SHAREDCLIPBOARDFSOBJINFO);
+                            pEntry->fInfo  = VBOX_SHAREDCLIPBOARD_INFO_FLAG_FSOBJINFO;
+                        }
                     }
                     else
@@ -1294,4 +1186,11 @@
 }
 
+/**
+ * Returns whether a given list handle is valid or not.
+ *
+ * @returns \c true if list handle is valid, \c false if not.
+ * @param   pTransfer           URI clipboard transfer to handle.
+ * @param   hList               List handle to check.
+ */
 bool SharedClipboardURITransferListHandleIsValid(PSHAREDCLIPBOARDURITRANSFER pTransfer, SHAREDCLIPBOARDLISTHANDLE hList)
 {
@@ -1373,4 +1272,25 @@
 }
 
+int SharedClipboardURILTransferSetRoots(PSHAREDCLIPBOARDURITRANSFER pTransfer, const char *pszRoots, size_t cbRoots)
+{
+    AssertPtrReturn(pTransfer, VERR_INVALID_POINTER);
+    AssertPtrReturn(pszRoots,  VERR_INVALID_POINTER);
+    AssertReturn(cbRoots,      VERR_INVALID_PARAMETER);
+
+    if (!RTStrIsValidEncoding(pszRoots))
+        return VERR_INVALID_PARAMETER;
+
+    int rc = VINF_SUCCESS;
+
+    pTransfer->lstRootEntries.clear();
+
+    pTransfer->lstRootEntries = RTCString(pszRoots, cbRoots - 1).split("\r\n");
+
+    LogFlowFunc(("cRoots=%RU32\n", pTransfer->lstRootEntries.size()));
+
+    LogFlowFuncLeaveRC(rc);
+    return rc;
+}
+
 /**
  * Resets an clipboard URI transfer.
@@ -1398,4 +1318,51 @@
 
     return pTransfer->pArea;
+}
+
+int SharedClipboardURILTransferGetRoots(PSHAREDCLIPBOARDURITRANSFER pTransfer, char **ppszRoots, uint32_t *pcRoots)
+{
+    AssertPtrReturn(pTransfer, VERR_INVALID_POINTER);
+    AssertPtrReturn(ppszRoots, VERR_INVALID_POINTER);
+
+    int rc = VINF_SUCCESS;
+
+    if (pTransfer->State.enmSource == SHAREDCLIPBOARDSOURCE_LOCAL)
+    {
+        char *pszRoots = NULL;
+
+        for (size_t i = 0; i < pTransfer->lstRootEntries.size(); ++i)
+        {
+            if (pszRoots)
+                rc = RTStrAAppend(&pszRoots, "\r\n");
+            if (RT_SUCCESS(rc))
+                rc = RTStrAAppend(&pszRoots, pTransfer->lstRootEntries.at(i).c_str());
+
+            if (RT_FAILURE(rc))
+                break;
+        }
+
+        if (RT_SUCCESS(rc))
+        {
+            LogFlowFunc(("Roots (%RU32):\n%s\n", pTransfer->lstRootEntries.size(), pszRoots));
+
+            *ppszRoots = pszRoots;
+            *pcRoots     = (uint32_t)pTransfer->lstRootEntries.size();
+        }
+        else
+        {
+            if (pszRoots)
+                RTStrFree(pszRoots);
+        }
+    }
+    else if (pTransfer->State.enmSource == SHAREDCLIPBOARDSOURCE_REMOTE)
+    {
+        if (pTransfer->ProviderIface.pfnGetRoots)
+            rc = pTransfer->ProviderIface.pfnGetRoots(&pTransfer->ProviderCtx, ppszRoots, pcRoots);
+        else
+            rc = VERR_NOT_SUPPORTED;
+    }
+
+    LogFlowFuncLeaveRC(rc);
+    return rc;
 }
 
@@ -1537,5 +1504,5 @@
     }
     else
-        rc = VERR_ALREADY_EXISTS;
+        rc = VINF_SUCCESS;
 
     LogFlowFuncLeaveRC(rc);
Index: /trunk/src/VBox/GuestHost/SharedClipboard/clipboard-win.cpp
===================================================================
--- /trunk/src/VBox/GuestHost/SharedClipboard/clipboard-win.cpp	(revision 79671)
+++ /trunk/src/VBox/GuestHost/SharedClipboard/clipboard-win.cpp	(revision 79672)
@@ -1030,20 +1030,6 @@
             LogRel(("Shared Clipboard: Adding guest file '%s'\n", pszFileUtf8));
 
-        #if 0
-            char    *pszFileURI;
-            uint32_t cchFileURI;
-            rc = SharedClipboardMetaDataConvertToFormat(pszFileUtf8, strlen(pszFileUtf8), SHAREDCLIPBOARDMETADATAFMT_URI_LIST,
-                                                        (void **)&pszFileURI, &cchFileURI);
-            if (RT_SUCCESS(rc))
-            {
-                LogFlowFunc(("\tURI is: %s (%RU32)\n", pszFileURI, cchFileURI));
-
-                rc = RTStrAAppendExN(&pszFiles, 1 /* cPairs */, pszFileURI, cchFileURI);
-                if (RT_SUCCESS(rc))
-                    cchFiles += cchFileURI;
-
-                RTStrFree(pszFileURI);
-            }
-        #endif
+            rc = RTStrAAppendExN(&pszFiles, 1 /* cPairs */, pszFileUtf8, strlen(pszFileUtf8));
+            cchFiles += (uint32_t)strlen(pszFileUtf8);
         }
 
Index: /trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc-uri.cpp
===================================================================
--- /trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc-uri.cpp	(revision 79671)
+++ /trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc-uri.cpp	(revision 79672)
@@ -73,4 +73,114 @@
 }
 
+DECLCALLBACK(int) vboxSvcClipboardURIGetRoots(PSHAREDCLIPBOARDPROVIDERCTX pCtx,
+                                              char **ppapszRoots, uint32_t *pcRoots)
+{
+    LogFlowFuncEnter();
+
+    PVBOXCLIPBOARDCLIENT pClient = (PVBOXCLIPBOARDCLIENT)pCtx->pvUser;
+    AssertPtr(pClient);
+
+    int rc;
+
+    size_t   cbRootsRecv = 0;
+
+    char    *pszRoots = NULL;
+    uint32_t cRoots   = 0;
+
+    /* There might be more than one message needed for retrieving all root items. */
+    for (;;)
+    {
+        PVBOXCLIPBOARDCLIENTMSG pMsg = vboxSvcClipboardMsgAlloc(VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_ROOTS,
+                                                                VBOX_SHARED_CLIPBOARD_CPARMS_ROOTS);
+        if (pMsg)
+        {
+            HGCMSvcSetU32(&pMsg->m_paParms[0], 0 /* uContextID */);
+            HGCMSvcSetU32(&pMsg->m_paParms[1], 0 /* fRoots */);
+            HGCMSvcSetU32(&pMsg->m_paParms[2], 0 /* fMore */);
+            HGCMSvcSetU32(&pMsg->m_paParms[3], 0 /* cRoots */);
+
+            uint32_t  cbData = _64K;
+            void     *pvData = RTMemAlloc(cbData);
+            AssertPtrBreakStmt(pvData, rc = VERR_NO_MEMORY);
+
+            HGCMSvcSetU32(&pMsg->m_paParms[4], cbData);
+            HGCMSvcSetPv (&pMsg->m_paParms[5], pvData, cbData);
+
+            rc = vboxSvcClipboardMsgAdd(pClient->pData, pMsg, true /* fAppend */);
+            if (RT_SUCCESS(rc))
+            {
+                int rc2 = SharedClipboardURITransferEventRegister(pCtx->pTransfer,
+                                                                  SHAREDCLIPBOARDURITRANSFEREVENTTYPE_GET_ROOTS);
+                AssertRC(rc2);
+
+                vboxSvcClipboardClientWakeup(pClient);
+            }
+        }
+        else
+            rc = VERR_NO_MEMORY;
+
+        if (RT_SUCCESS(rc))
+        {
+            PSHAREDCLIPBOARDURITRANSFERPAYLOAD pPayload;
+            rc = SharedClipboardURITransferEventWait(pCtx->pTransfer, SHAREDCLIPBOARDURITRANSFEREVENTTYPE_GET_ROOTS,
+                                                     30 * 1000 /* Timeout in ms */, &pPayload);
+            if (RT_SUCCESS(rc))
+            {
+                PVBOXCLIPBOARDROOTS pRoots = (PVBOXCLIPBOARDROOTS)pPayload->pvData;
+                Assert(pPayload->cbData == sizeof(VBOXCLIPBOARDROOTS));
+
+                LogFlowFunc(("cbRoots=%RU32, fRoots=%RU32, fMore=%RTbool\n", pRoots->cbRoots, pRoots->fRoots, pRoots->fMore));
+
+                if (!pRoots->cbRoots)
+                    break;
+                AssertPtr(pRoots->pszRoots);
+
+                if (pszRoots == NULL)
+                    pszRoots = (char *)RTMemDup((void *)pRoots->pszRoots, pRoots->cbRoots);
+                else
+                    pszRoots = (char *)RTMemRealloc(pszRoots, cbRootsRecv + pRoots->cbRoots);
+
+                AssertPtrBreakStmt(pszRoots, rc = VERR_NO_MEMORY);
+
+                cbRootsRecv += pRoots->cbRoots;
+
+                if (cbRootsRecv > _32M) /* Don't allow more than 32MB root entries for now. */
+                {
+                    rc = VERR_ALLOCATION_TOO_BIG; /** @todo Find a better rc. */
+                    break;
+                }
+
+                cRoots += pRoots->cRoots;
+
+                const bool fDone = !RT_BOOL(pRoots->fMore); /* More root entries to be retrieved? Otherwise bail out. */
+
+                SharedClipboardURITransferPayloadFree(pPayload);
+
+                if (fDone)
+                    break;
+            }
+        }
+
+        if (RT_FAILURE(rc))
+            break;
+    }
+
+    if (RT_SUCCESS(rc))
+    {
+        LogFlowFunc(("cRoots=%RU32\n", cRoots));
+
+        *ppapszRoots = pszRoots;
+        *pcRoots     = cRoots;
+    }
+    else
+    {
+        RTMemFree(pszRoots);
+        pszRoots = NULL;
+    }
+
+    LogFlowFuncLeave();
+    return rc;
+}
+
 DECLCALLBACK(int) vboxSvcClipboardURIListOpen(PSHAREDCLIPBOARDPROVIDERCTX pCtx,
                                               PVBOXCLIPBOARDLISTOPENPARMS pOpenParms, PSHAREDCLIPBOARDLISTHANDLE phList)
@@ -403,4 +513,39 @@
                     break;
             }
+        }
+    }
+    else
+        rc = VERR_INVALID_PARAMETER;
+
+    LogFlowFuncLeaveRC(rc);
+    return rc;
+}
+
+int VBoxSvcClipboardURIGetRoots(uint32_t cParms, VBOXHGCMSVCPARM paParms[],
+                                PVBOXCLIPBOARDROOTS pRoots)
+{
+    int rc;
+
+    if (cParms == VBOX_SHARED_CLIPBOARD_CPARMS_ROOTS)
+    {
+        /* Note: Context ID (paParms[0]) not used yet. */
+        rc = HGCMSvcGetU32(&paParms[1], &pRoots->fRoots);
+        if (RT_SUCCESS(rc))
+        {
+            uint32_t fMore;
+            rc = HGCMSvcGetU32(&paParms[2], &fMore);
+            if (RT_SUCCESS(rc))
+                pRoots->fMore = RT_BOOL(fMore);
+        }
+        if (RT_SUCCESS(rc))
+            rc = HGCMSvcGetU32(&paParms[3], &pRoots->cRoots);
+        if (RT_SUCCESS(rc))
+        {
+            uint32_t cbRoots;
+            rc = HGCMSvcGetU32(&paParms[4], &cbRoots);
+            if (RT_SUCCESS(rc))
+                rc = HGCMSvcGetPv(&paParms[5], (void **)&pRoots->pszRoots, &pRoots->cbRoots);
+
+            AssertReturn(cbRoots == pRoots->cbRoots, VERR_INVALID_PARAMETER);
         }
     }
@@ -582,7 +727,15 @@
             rc = HGCMSvcGetU32(&paParms[2], &pListEntry->fInfo);
         if (RT_SUCCESS(rc))
-            rc = HGCMSvcGetU32(&paParms[3], &pListEntry->cbInfo);
-        if (RT_SUCCESS(rc))
-            rc = HGCMSvcGetPv(&paParms[4], &pListEntry->pvInfo, &pListEntry->cbInfo);
+            rc = HGCMSvcGetPv(&paParms[3], (void **)&pListEntry->pszName, &pListEntry->cbName);
+        if (RT_SUCCESS(rc))
+        {
+            uint32_t cbInfo;
+            rc = HGCMSvcGetU32(&paParms[4], &cbInfo);
+            if (RT_SUCCESS(rc))
+            {
+                rc = HGCMSvcGetPv(&paParms[5], &pListEntry->pvInfo, &pListEntry->cbInfo);
+                AssertReturn(cbInfo == pListEntry->cbInfo, VERR_INVALID_PARAMETER);
+            }
+        }
 
         if (RT_SUCCESS(rc))
@@ -846,4 +999,5 @@
                         if (enmDir == SHAREDCLIPBOARDURITRANSFERDIR_READ)
                         {
+                            creationCtx.Interface.pfnGetRoots      = vboxSvcClipboardURIGetRoots;
                             creationCtx.Interface.pfnListHdrRead   = vboxSvcClipboardURIListHdrRead;
                             creationCtx.Interface.pfnListEntryRead = vboxSvcClipboardURIListEntryRead;
@@ -921,4 +1075,23 @@
         {
             rc = VBoxSvcClipboardURITransferHandleReply(pClient, pTransfer, cParms, paParms);
+            break;
+        }
+
+        case VBOX_SHARED_CLIPBOARD_GUEST_FN_ROOTS:
+        {
+            VBOXCLIPBOARDROOTS Roots;
+            rc = VBoxSvcClipboardURIGetRoots(cParms, paParms, &Roots);
+            if (RT_SUCCESS(rc))
+            {
+                void    *pvData = SharedClipboardURIRootsDup(&Roots);
+                uint32_t cbData = sizeof(VBOXCLIPBOARDROOTS);
+
+                PSHAREDCLIPBOARDURITRANSFERPAYLOAD pPayload;
+                rc = SharedClipboardURITransferPayloadAlloc(SHAREDCLIPBOARDURITRANSFEREVENTTYPE_GET_ROOTS,
+                                                            pvData, cbData, &pPayload);
+                if (RT_SUCCESS(rc))
+                    rc = SharedClipboardURITransferEventSignal(pTransfer, SHAREDCLIPBOARDURITRANSFEREVENTTYPE_GET_ROOTS,
+                                                               pPayload);
+            }
             break;
         }
Index: /trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc.cpp
===================================================================
--- /trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc.cpp	(revision 79671)
+++ /trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc.cpp	(revision 79672)
@@ -507,85 +507,91 @@
      * Return information about the first message if one is pending in the list.
      */
-    PVBOXCLIPBOARDCLIENTMSG pFirstMsg = pClient->pData->queueMsg.first();
-    if (pFirstMsg)
-    {
-        LogFlowFunc(("First message is: %RU32 %s (%RU32 parms)\n",
-                     pFirstMsg->m_uMsg, VBoxSvcClipboardHostMsgToStr(pFirstMsg->m_uMsg), pFirstMsg->m_cParms));
-
-        ASSERT_GUEST_MSG_RETURN(pFirstMsg->m_uMsg == idMsgExpected || idMsgExpected == UINT32_MAX,
-                                ("idMsg=%u (%s) cParms=%u, caller expected %u (%s) and %u\n",
-                                 pFirstMsg->m_uMsg, VBoxSvcClipboardHostMsgToStr(pFirstMsg->m_uMsg), pFirstMsg->m_uMsg,
-                                 idMsgExpected, VBoxSvcClipboardHostMsgToStr(idMsgExpected), cParms),
-                                VERR_MISMATCH);
-        ASSERT_GUEST_MSG_RETURN(pFirstMsg->m_cParms == cParms,
-                                ("idMsg=%u (%s) cParms=%u, caller expected %u (%s) and %u\n",
-                                 pFirstMsg->m_uMsg, VBoxSvcClipboardHostMsgToStr(pFirstMsg->m_uMsg), pFirstMsg->m_cParms,
-                                 idMsgExpected, VBoxSvcClipboardHostMsgToStr(idMsgExpected), cParms),
-                                VERR_WRONG_PARAMETER_COUNT);
-
-        /* Check the parameter types. */
-        for (uint32_t i = 0; i < cParms; i++)
-            ASSERT_GUEST_MSG_RETURN(pFirstMsg->m_paParms[i].type == paParms[i].type,
-                                    ("param #%u: type %u, caller expected %u (idMsg=%u %s)\n", i, pFirstMsg->m_paParms[i].type,
-                                     paParms[i].type, pFirstMsg->m_uMsg, VBoxSvcClipboardHostMsgToStr(pFirstMsg->m_uMsg)),
-                                    VERR_WRONG_PARAMETER_TYPE);
-        /*
-         * Copy out the parameters.
-         *
-         * No assertions on buffer overflows, and keep going till the end so we can
-         * communicate all the required buffer sizes.
-         */
-        int rc = VINF_SUCCESS;
-        for (uint32_t i = 0; i < cParms; i++)
-            switch (pFirstMsg->m_paParms[i].type)
-            {
-                case VBOX_HGCM_SVC_PARM_32BIT:
-                    paParms[i].u.uint32 = pFirstMsg->m_paParms[i].u.uint32;
-                    break;
-
-                case VBOX_HGCM_SVC_PARM_64BIT:
-                    paParms[i].u.uint64 = pFirstMsg->m_paParms[i].u.uint64;
-                    break;
-
-                case VBOX_HGCM_SVC_PARM_PTR:
+    if (!pClient->pData->queueMsg.isEmpty())
+    {
+        PVBOXCLIPBOARDCLIENTMSG pFirstMsg = pClient->pData->queueMsg.first();
+        if (pFirstMsg)
+        {
+            LogFlowFunc(("First message is: %RU32 %s (%RU32 parms)\n",
+                         pFirstMsg->m_uMsg, VBoxSvcClipboardHostMsgToStr(pFirstMsg->m_uMsg), pFirstMsg->m_cParms));
+
+            ASSERT_GUEST_MSG_RETURN(pFirstMsg->m_uMsg == idMsgExpected || idMsgExpected == UINT32_MAX,
+                                    ("idMsg=%u (%s) cParms=%u, caller expected %u (%s) and %u\n",
+                                     pFirstMsg->m_uMsg, VBoxSvcClipboardHostMsgToStr(pFirstMsg->m_uMsg), pFirstMsg->m_cParms,
+                                     idMsgExpected, VBoxSvcClipboardHostMsgToStr(idMsgExpected), cParms),
+                                    VERR_MISMATCH);
+            ASSERT_GUEST_MSG_RETURN(pFirstMsg->m_cParms == cParms,
+                                    ("idMsg=%u (%s) cParms=%u, caller expected %u (%s) and %u\n",
+                                     pFirstMsg->m_uMsg, VBoxSvcClipboardHostMsgToStr(pFirstMsg->m_uMsg), pFirstMsg->m_cParms,
+                                     idMsgExpected, VBoxSvcClipboardHostMsgToStr(idMsgExpected), cParms),
+                                    VERR_WRONG_PARAMETER_COUNT);
+
+            /* Check the parameter types. */
+            for (uint32_t i = 0; i < cParms; i++)
+                ASSERT_GUEST_MSG_RETURN(pFirstMsg->m_paParms[i].type == paParms[i].type,
+                                        ("param #%u: type %u, caller expected %u (idMsg=%u %s)\n", i, pFirstMsg->m_paParms[i].type,
+                                         paParms[i].type, pFirstMsg->m_uMsg, VBoxSvcClipboardHostMsgToStr(pFirstMsg->m_uMsg)),
+                                        VERR_WRONG_PARAMETER_TYPE);
+            /*
+             * Copy out the parameters.
+             *
+             * No assertions on buffer overflows, and keep going till the end so we can
+             * communicate all the required buffer sizes.
+             */
+            int rc = VINF_SUCCESS;
+            for (uint32_t i = 0; i < cParms; i++)
+                switch (pFirstMsg->m_paParms[i].type)
                 {
-                    uint32_t const cbSrc = pFirstMsg->m_paParms[i].u.pointer.size;
-                    uint32_t const cbDst = paParms[i].u.pointer.size;
-                    paParms[i].u.pointer.size = cbSrc; /** @todo Check if this is safe in other layers...
-                                                        * Update: Safe, yes, but VMMDevHGCM doesn't pass it along. */
-                    if (cbSrc <= cbDst)
-                        memcpy(paParms[i].u.pointer.addr, pFirstMsg->m_paParms[i].u.pointer.addr, cbSrc);
-                    else
-                        rc = VERR_BUFFER_OVERFLOW;
-                    break;
+                    case VBOX_HGCM_SVC_PARM_32BIT:
+                        paParms[i].u.uint32 = pFirstMsg->m_paParms[i].u.uint32;
+                        break;
+
+                    case VBOX_HGCM_SVC_PARM_64BIT:
+                        paParms[i].u.uint64 = pFirstMsg->m_paParms[i].u.uint64;
+                        break;
+
+                    case VBOX_HGCM_SVC_PARM_PTR:
+                    {
+                        uint32_t const cbSrc = pFirstMsg->m_paParms[i].u.pointer.size;
+                        uint32_t const cbDst = paParms[i].u.pointer.size;
+                        paParms[i].u.pointer.size = cbSrc; /** @todo Check if this is safe in other layers...
+                                                            * Update: Safe, yes, but VMMDevHGCM doesn't pass it along. */
+                        if (cbSrc <= cbDst)
+                            memcpy(paParms[i].u.pointer.addr, pFirstMsg->m_paParms[i].u.pointer.addr, cbSrc);
+                        else
+                        {
+                            AssertMsgFailed(("#%u: cbSrc=%RU32 is bigger than cbDst=%RU32\n", i, cbSrc, cbDst));
+                            rc = VERR_BUFFER_OVERFLOW;
+                        }
+                        break;
+                    }
+
+                    default:
+                        AssertMsgFailed(("#%u: %u\n", i, pFirstMsg->m_paParms[i].type));
+                        rc = VERR_INTERNAL_ERROR;
+                        break;
                 }
-
-                default:
-                    AssertMsgFailed(("#%u: %u\n", i, pFirstMsg->m_paParms[i].type));
-                    rc = VERR_INTERNAL_ERROR;
-                    break;
+            if (RT_SUCCESS(rc))
+            {
+                /*
+                 * Complete the message and remove the pending message unless the
+                 * guest raced us and cancelled this call in the meantime.
+                 */
+                AssertPtr(g_pHelpers);
+                rc = g_pHelpers->pfnCallComplete(hCall, rc);
+
+                LogFlowFunc(("[Client %RU32] pfnCallComplete -> %Rrc\n", pClient->uClientID, rc));
+
+                if (rc != VERR_CANCELLED)
+                {
+                    pClient->pData->queueMsg.removeFirst();
+                    vboxSvcClipboardMsgFree(pFirstMsg);
+                }
+
+                return VINF_HGCM_ASYNC_EXECUTE; /* The caller must not complete it. */
             }
-        if (RT_SUCCESS(rc))
-        {
-            /*
-             * Complete the message and remove the pending message unless the
-             * guest raced us and cancelled this call in the meantime.
-             */
-            AssertPtr(g_pHelpers);
-            rc = g_pHelpers->pfnCallComplete(hCall, rc);
-
-            LogFlowFunc(("[Client %RU32] pfnCallComplete -> %Rrc\n", pClient->uClientID, rc));
-
-            if (rc != VERR_CANCELLED)
-            {
-                pClient->pData->queueMsg.removeFirst();
-                vboxSvcClipboardMsgFree(pFirstMsg);
-            }
-
-            return VINF_HGCM_ASYNC_EXECUTE; /* The caller must not complete it. */
+
+            LogFlowFunc(("[Client %RU32] Returning %Rrc\n", pClient->uClientID, rc));
+            return rc;
         }
-
-        LogFlowFunc(("[Client %RU32] Returning %Rrc\n", pClient->uClientID, rc));
-        return rc;
     }
 
@@ -1391,9 +1397,7 @@
 #ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
             rc = vboxSvcClipboardURIHandler(pClient, callHandle, u32Function, cParms, paParms, tsArrival);
-            if (RT_SUCCESS(rc))
-            {
-                /* The URI handler does deferring on its own. */
-                fDefer = true;
-            }
+
+            /* The URI handler does deferring on its own, so never do any call completion here. */
+            fDefer = true;
 #else
             rc = VERR_NOT_IMPLEMENTED;
