Index: /trunk/include/VBox/GuestHost/SharedClipboard-uri.h
===================================================================
--- /trunk/include/VBox/GuestHost/SharedClipboard-uri.h	(revision 79629)
+++ /trunk/include/VBox/GuestHost/SharedClipboard-uri.h	(revision 79630)
@@ -48,7 +48,7 @@
 
 /** A Shared Clipboard list handle. */
-typedef uint64_t VBOXCLIPBOARDLISTHANDLE;
+typedef uint64_t SHAREDCLIPBOARDLISTHANDLE;
 /** Pointer to a Shared Clipboard list handle. */
-typedef VBOXCLIPBOARDLISTHANDLE *PVBOXCLIPBOARDLISTHANDLE;
+typedef SHAREDCLIPBOARDLISTHANDLE *PSHAREDCLIPBOARDLISTHANDLE;
 
 /** Specifies an invalid Shared Clipboard list handle. */
@@ -546,16 +546,61 @@
 
 /**
- * Structure for a Shared Clipboard list header.
+ * Structure for keeping a reply message.
+ */
+typedef struct _VBOXCLIPBOARDREPLY
+{
+    /** Message type of type VBOX_SHAREDCLIPBOARD_REPLYMSGTYPE_XXX. */
+    uint32_t uType;
+    /** IPRT result of overall operation. Note: int vs. uint32! */
+    uint32_t rc;
+    union
+    {
+        struct
+        {
+            SHAREDCLIPBOARDLISTHANDLE uHandle;
+        } ListOpen;
+        struct
+        {
+            SHAREDCLIPBOARDOBJHANDLE uHandle;
+        } ObjOpen;
+    } u;
+    /** Pointer to optional payload. */
+    void    *pvPayload;
+    /** Payload size (in bytes). */
+    uint32_t cbPayload;
+} VBOXCLIPBOARDREPLY, *PVBOXCLIPBOARDREPLY;
+
+/**
+ * Structure for maintaining Shared Clipboard list open paramters.
+ */
+typedef struct _VBOXCLIPBOARDLISTOPENPARMS
+{
+    /** Listing flags (see VBOX_SHAREDCLIPBOARD_LIST_FLAG_XXX). */
+    uint32_t fList;
+    /** Size (in bytes) of the filter string. */
+    uint32_t cbFilter;
+    /** Filter string. DOS wilcard-style. */
+    char    *pszFilter;
+    /** Size (in bytes) of the listing path. */
+    uint32_t cbPath;
+    /** Listing path (absolute). If empty or NULL the listing's root path will be opened. */
+    char    *pszPath;
+} VBOXCLIPBOARDLISTOPENPARMS, *PVBOXCLIPBOARDLISTOPENPARMS;
+
+/**
+ * Structure for keeping a Shared Clipboard list header.
  */
 typedef struct _VBOXCLIPBOARDLISTHDR
 {
-    uint32_t fList;                 /* IN */
-    uint32_t cbFilter;              /* IN */
-    char    *pszFilter;             /* IN */
-    uint32_t fFeatures;             /* OUT */
-    uint64_t cTotalObjects;         /* OUT */
-    uint64_t cbTotalSize;           /* OUT */
-    uint32_t enmCompression;        /* IN / OUT */
-    uint32_t enmChecksumType;       /* IN / OUT */
+    /** Feature flag(s). Not being used atm. */
+    uint32_t fFeatures;
+    /** Total objects returned. */
+    uint64_t cTotalObjects;
+    /** Total size (in bytes) returned. */
+    uint64_t cbTotalSize;
+    /** Compression being method used. Not implemented yet. */
+    uint32_t enmCompression;
+    /** Checksum type being used. Not implemented yet. */
+    uint32_t enmChecksumType;
 } VBOXCLIPBOARDLISTHDR, *PVBOXCLIPBOARDLISTHDR;
 
@@ -565,6 +610,9 @@
 typedef struct _VBOXCLIPBOARDLISTENTRY
 {
+    /** Information flag(s). */
     uint32_t fInfo;
+    /** Size (in bytes) of the actual list entry. */
     uint32_t cbInfo;
+    /** Data of the actual list entry. */
     void    *pvInfo;
 } VBOXCLIPBOARDLISTENTRY, *PVBOXCLIPBOARDLISTENTRY;
@@ -575,5 +623,6 @@
 typedef struct _VBOXCLIPBOARDOBJHDR
 {
-    uint32_t                    enmType;
+    /** Header type. Currently not being used. */
+    uint32_t enmType;
 } VBOXCLIPBOARDOBJHDR, *PVBOXCLIPBOARDOBJHDR;
 
@@ -589,6 +638,8 @@
     /** Object is a file. */
     SHAREDCLIPBOARDAREAOBJTYPE_FILE,
+    /** Object is a symbolic link. */
+    SHAREDCLIPBOARDAREAOBJTYPE_SYMLINK,
     /** The usual 32-bit hack. */
-    SHAREDCLIPBOARDAREAOBJTYPE__32Bit_Hack = 0x7fffffff
+    SHAREDCLIPBOARDAREAOBJTYPE_32Bit_Hack = 0x7fffffff
 } SHAREDCLIPBOARDAREAOBJTYPE;
 
@@ -771,6 +822,12 @@
 bool SharedClipboardURIListHdrIsValid(PVBOXCLIPBOARDLISTHDR pListHdr);
 
+int SharedClipboardURIListOpenParmsCopy(PVBOXCLIPBOARDLISTOPENPARMS pDst, PVBOXCLIPBOARDLISTOPENPARMS pSrc);
+PVBOXCLIPBOARDLISTOPENPARMS SharedClipboardURIListOpenParmsDup(PVBOXCLIPBOARDLISTOPENPARMS pParms);
+int SharedClipboardURIListOpenParmsInit(PVBOXCLIPBOARDLISTOPENPARMS pParms);
+void SharedClipboardURIListOpenParmsDestroy(PVBOXCLIPBOARDLISTOPENPARMS pParms);
+
 int SharedClipboardURIListEntryAlloc(PVBOXCLIPBOARDLISTENTRY *ppListEntry);
 void SharedClipboardURIListEntryFree(PVBOXCLIPBOARDLISTENTRY pListEntry);
+int SharedClipboardURIListEntryCopy(PVBOXCLIPBOARDLISTENTRY pDst, PVBOXCLIPBOARDLISTENTRY pSrc);
 PVBOXCLIPBOARDLISTENTRY SharedClipboardURIListEntryDup(PVBOXCLIPBOARDLISTENTRY pListEntry);
 int SharedClipboardURIListEntryInit(PVBOXCLIPBOARDLISTENTRY pListEntry);
@@ -803,42 +860,77 @@
     SHAREDCLIPBOARDURITRANSFER *pTransfer;
     SHAREDCLIPBOARDOBJHANDLE    uHandle;
-    SHAREDCLIPBOARDFSOBJINFO   *pObjInfo;
+} SHAREDCLIPBOARDCLIENTURIOBJCTX, *PSHAREDCLIPBOARDCLIENTURIOBJCTX;
+
+typedef struct _SHAREDCLIPBOARDURITRANSFEROBJSTATE
+{
     uint64_t                    cbProcessed;
-} SHAREDCLIPBOARDCLIENTURIOBJCTX, *PSHAREDCLIPBOARDCLIENTURIOBJCTX;
-
-/**
- * Enumeration specifying an URI transfer status.
- */
-typedef enum _SHAREDCLIPBOARDURITRANSFERSTATUS
-{
-    /** No status set. */
-    SHAREDCLIPBOARDURITRANSFERSTATUS_NONE = 0,
-    /** The transfer has been announced but is not running yet. */
-    SHAREDCLIPBOARDURITRANSFERSTATUS_READY,
-    /** The transfer is active and running. */
-    SHAREDCLIPBOARDURITRANSFERSTATUS_RUNNING,
-    /** The usual 32-bit hack. */
-    SHAREDCLIPBOARDURITRANSFERSTATUS_32BIT_HACK = 0x7fffffff
-} SHAREDCLIPBOARDURITRANSFERSTATUS;
-
+} SHAREDCLIPBOARDURITRANSFEROBJSTATE, *PSHAREDCLIPBOARDURITRANSFEROBJSTATE;
+
+typedef struct _SHAREDCLIPBOARDURITRANSFEROBJ
+{
+    SHAREDCLIPBOARDOBJHANDLE           uHandle;
+    char                              *pszPathAbs;
+    SHAREDCLIPBOARDFSOBJINFO           objInfo;
+    SHAREDCLIPBOARDSOURCE              enmSource;
+    SHAREDCLIPBOARDURITRANSFEROBJSTATE State;
+} SHAREDCLIPBOARDURITRANSFEROBJ, *PSHAREDCLIPBOARDURITRANSFEROBJ;
+
+/** No status set. */
+#define SHAREDCLIPBOARDURITRANSFERSTATUS_NONE           0
+/** The transfer has been announced but is not running yet. */
+#define SHAREDCLIPBOARDURITRANSFERSTATUS_READY          1
+/** The transfer is active and running. */
+#define SHAREDCLIPBOARDURITRANSFERSTATUS_RUNNING        2
+/** The transfer has been completed. */
+#define SHAREDCLIPBOARDURITRANSFERSTATUS_COMPLETED      3
+/** The transfer has been canceled. */
+#define SHAREDCLIPBOARDURITRANSFERSTATUS_CANCELED       4
+/** The transfer ran into an unrecoverable error. */
+#define SHAREDCLIPBOARDURITRANSFERSTATUS_ERROR          5
+
+/** Defines a transfer status. */
+typedef uint32_t SHAREDCLIPBOARDURITRANSFERSTATUS;
+
+/**
+ * Structure for an (optional) URI transfer event payload.
+ */
 typedef struct _SHAREDCLIPBOARDURITRANSFERPAYLOAD
 {
+    /** Payload ID; currently unused. */
     uint32_t uID;
+    /** Pointer to actual payload data. */
     void    *pvData;
+    /** Size (in bytes) of actual payload data. */
     uint32_t cbData;
 } SHAREDCLIPBOARDURITRANSFERPAYLOAD, *PSHAREDCLIPBOARDURITRANSFERPAYLOAD;
 
+/**
+ * Structure for maintaining an URI transfer event.
+ */
 typedef struct _SHAREDCLIPBOARDURITRANSFEREVENT
 {
+    /** Event semaphore for signalling the event. */
     RTSEMEVENT                         hEventSem;
+    /** Payload to this event. Optional and can be NULL. */
     PSHAREDCLIPBOARDURITRANSFERPAYLOAD pPayload;
 } SHAREDCLIPBOARDURITRANSFEREVENT, *PSHAREDCLIPBOARDURITRANSFEREVENT;
 
+/**
+ * Enumeration for an URI transfer event type.
+ */
 typedef enum _SHAREDCLIPBOARDURITRANSFEREVENTTYPE
 {
     SHAREDCLIPBOARDURITRANSFEREVENTTYPE_UNKNOWN,
+    SHAREDCLIPBOARDURITRANSFEREVENTTYPE_LIST_OPEN,
+    SHAREDCLIPBOARDURITRANSFEREVENTTYPE_LIST_CLOSE,
     SHAREDCLIPBOARDURITRANSFEREVENTTYPE_LIST_HDR_READ,
+    SHAREDCLIPBOARDURITRANSFEREVENTTYPE_LIST_HDR_WRITE,
     SHAREDCLIPBOARDURITRANSFEREVENTTYPE_LIST_ENTRY_READ,
-    SHAREDCLIPBOARDURITRANSFEREVENTTYPE_FILE_DATA_READ,
+    SHAREDCLIPBOARDURITRANSFEREVENTTYPE_LIST_ENTRY_WRITE,
+    SHAREDCLIPBOARDURITRANSFEREVENTTYPE_FILE_OPEN,
+    SHAREDCLIPBOARDURITRANSFEREVENTTYPE_FILE_CLOSE,
+    SHAREDCLIPBOARDURITRANSFEREVENTTYPE_FILE_READ,
+    SHAREDCLIPBOARDURITRANSFEREVENTTYPE_FILE_WRITE,
+    SHAREDCLIPBOARDURITRANSFEREVENTTYPE_ERROR,
     /** Marks the end of the event list. */
     SHAREDCLIPBOARDURITRANSFEREVENTTYPE_LAST,
@@ -847,10 +939,41 @@
 } SHAREDCLIPBOARDURITRANSFEREVENTTYPE;
 
+/** Map of URI transfer events.
+ *  The key specifies the event type of SHAREDCLIPBOARDURITRANSFEREVENTTYPE. */
 typedef std::map<uint32_t, SHAREDCLIPBOARDURITRANSFEREVENT *> SharedClipboardURITransferEventMap;
 
-typedef struct _SHAREDCLIPBOARDURITRANSFEREVENTS
-{
-    SharedClipboardURITransferEventMap *pMap;
-} SHAREDCLIPBOARDURITRANSFEREVENTS, *PSHAREDCLIPBOARDURITRANSFEREVENTS;
+typedef struct _SHAREDCLIPBOARDURILISTHANDLEINFO
+{
+    VBOXCLIPBOARDLISTOPENPARMS OpenParms;
+    RTFMODE                     fMode;
+    union
+    {
+        struct
+        {
+            union
+            {
+                RTDIR  hDirRoot;
+                RTFILE hFile;
+            };
+        } Local;
+    } u;
+} SHAREDCLIPBOARDURILISTHANDLEINFO, *PSHAREDCLIPBOARDURILISTHANDLEINFO;
+
+typedef struct _SHAREDCLIPBOARDOBJHANDLEINFO
+{
+    union
+    {
+        struct
+        {
+            RTDIR hDirRoot;
+        } Local;
+    } u;
+} SHAREDCLIPBOARDURIOBJHANDLEINFO, *PSHAREDCLIPBOARDURIOBJHANDLEINFO;
+
+/** Map of URI list handles.
+ *  The key specifies the list handle. */
+typedef std::map<SHAREDCLIPBOARDLISTHANDLE, SHAREDCLIPBOARDURILISTHANDLEINFO *> SharedClipboardURIListMap;
+
+typedef std::map<SHAREDCLIPBOARDOBJHANDLE, SHAREDCLIPBOARDURILISTHANDLEINFO *> SharedClipboardURIObjMap;
 
 /**
@@ -866,6 +989,4 @@
     /** The transfer's source. */
     SHAREDCLIPBOARDSOURCE               enmSource;
-    /** Context of current object being handled. */
-    SHAREDCLIPBOARDCLIENTURIOBJCTX      ObjCtx;
 } SHAREDCLIPBOARDURITRANSFERSTATE, *PSHAREDCLIPBOARDURITRANSFERSTATE;
 
@@ -890,4 +1011,9 @@
     typedef RT_CONCAT(FNSHAREDCLIPBOARDPROVIDER, a_Name) RT_CONCAT(*PFNSHAREDCLIPBOARDPROVIDER, a_Name);
 
+/** Defines an URI clipboard provider function declaration with additional parameters. */
+#define SHAREDCLIPBOARDPROVIDERFUNCDECLRET(a_Ret, a_Name, ...) \
+    typedef DECLCALLBACK(a_Ret) RT_CONCAT(FNSHAREDCLIPBOARDPROVIDER, a_Name)(PSHAREDCLIPBOARDPROVIDERCTX, __VA_ARGS__); \
+    typedef RT_CONCAT(FNSHAREDCLIPBOARDPROVIDER, a_Name) RT_CONCAT(*PFNSHAREDCLIPBOARDPROVIDER, a_Name);
+
 /** Defines an URI clipboard provider function declaration (no additional parameters). */
 #define SHAREDCLIPBOARDPROVIDERFUNCDECLVOID(a_Name) \
@@ -901,14 +1027,17 @@
 SHAREDCLIPBOARDPROVIDERFUNCDECLVOID(TRANSFEROPEN)
 SHAREDCLIPBOARDPROVIDERFUNCDECLVOID(TRANSFERCLOSE)
-SHAREDCLIPBOARDPROVIDERFUNCDECL(LISTOPEN, PVBOXCLIPBOARDLISTHDR pListHdr, PVBOXCLIPBOARDLISTHANDLE phList)
-SHAREDCLIPBOARDPROVIDERFUNCDECL(LISTCLOSE, VBOXCLIPBOARDLISTHANDLE hList);
-SHAREDCLIPBOARDPROVIDERFUNCDECL(LISTHDRREAD, VBOXCLIPBOARDLISTHANDLE hList, PVBOXCLIPBOARDLISTHDR pListHdr)
-SHAREDCLIPBOARDPROVIDERFUNCDECL(LISTHDRWRITE, VBOXCLIPBOARDLISTHANDLE hList, PVBOXCLIPBOARDLISTHDR pListHdr)
-SHAREDCLIPBOARDPROVIDERFUNCDECL(LISTENTRYREAD, VBOXCLIPBOARDLISTHANDLE hList, PVBOXCLIPBOARDLISTENTRY pEntry)
-SHAREDCLIPBOARDPROVIDERFUNCDECL(LISTENTRYWRITE, VBOXCLIPBOARDLISTHANDLE hList, PVBOXCLIPBOARDLISTENTRY pEntry)
+SHAREDCLIPBOARDPROVIDERFUNCDECL(LISTOPEN, PVBOXCLIPBOARDLISTOPENPARMS pOpenParms, PSHAREDCLIPBOARDLISTHANDLE phList)
+SHAREDCLIPBOARDPROVIDERFUNCDECL(LISTCLOSE, SHAREDCLIPBOARDLISTHANDLE hList);
+SHAREDCLIPBOARDPROVIDERFUNCDECL(LISTHDRREAD, SHAREDCLIPBOARDLISTHANDLE hList, PVBOXCLIPBOARDLISTHDR pListHdr)
+SHAREDCLIPBOARDPROVIDERFUNCDECL(LISTHDRWRITE, SHAREDCLIPBOARDLISTHANDLE hList, PVBOXCLIPBOARDLISTHDR pListHdr)
+SHAREDCLIPBOARDPROVIDERFUNCDECL(LISTENTRYREAD, SHAREDCLIPBOARDLISTHANDLE hList, PVBOXCLIPBOARDLISTENTRY pEntry)
+SHAREDCLIPBOARDPROVIDERFUNCDECL(LISTENTRYWRITE, SHAREDCLIPBOARDLISTHANDLE hList, PVBOXCLIPBOARDLISTENTRY pEntry)
 SHAREDCLIPBOARDPROVIDERFUNCDECL(OBJOPEN, const char *pszPath, PVBOXCLIPBOARDCREATEPARMS pCreateParms, PSHAREDCLIPBOARDOBJHANDLE phObj)
 SHAREDCLIPBOARDPROVIDERFUNCDECL(OBJCLOSE, SHAREDCLIPBOARDOBJHANDLE hObj)
 SHAREDCLIPBOARDPROVIDERFUNCDECL(OBJREAD, SHAREDCLIPBOARDOBJHANDLE hObj, void *pvData, uint32_t cbData, uint32_t fFlags, uint32_t *pcbRead)
 SHAREDCLIPBOARDPROVIDERFUNCDECL(OBJWRITE, SHAREDCLIPBOARDOBJHANDLE hObj, void *pvData, uint32_t cbData, uint32_t fFlags, uint32_t *pcbWritten)
+SHAREDCLIPBOARDPROVIDERFUNCDECLRET(uint64_t, OBJGETSIZE, SHAREDCLIPBOARDOBJHANDLE hObj)
+SHAREDCLIPBOARDPROVIDERFUNCDECLRET(uint64_t, OBJGETPROCESSED, SHAREDCLIPBOARDOBJHANDLE hObj)
+SHAREDCLIPBOARDPROVIDERFUNCDECLRET(const char *, OBJGETPATH, SHAREDCLIPBOARDOBJHANDLE hObj)
 
 /**
@@ -919,7 +1048,5 @@
     SHAREDCLIPBOARDPROVIDERFUNCMEMBER(TRANSFEROPEN, pfnTransferOpen);
     SHAREDCLIPBOARDPROVIDERFUNCMEMBER(TRANSFERCLOSE, pfnTransferClose);
-    /** Optional. */
     SHAREDCLIPBOARDPROVIDERFUNCMEMBER(LISTOPEN, pfnListOpen);
-    /** Optional. */
     SHAREDCLIPBOARDPROVIDERFUNCMEMBER(LISTCLOSE, pfnListClose);
     SHAREDCLIPBOARDPROVIDERFUNCMEMBER(LISTHDRREAD, pfnListHdrRead);
@@ -931,4 +1058,7 @@
     SHAREDCLIPBOARDPROVIDERFUNCMEMBER(OBJREAD, pfnObjRead);
     SHAREDCLIPBOARDPROVIDERFUNCMEMBER(OBJWRITE, pfnObjWrite);
+    SHAREDCLIPBOARDPROVIDERFUNCMEMBER(OBJGETSIZE, pfnObjGetSize);
+    SHAREDCLIPBOARDPROVIDERFUNCMEMBER(OBJGETPROCESSED, pfnObjGetProcessed);
+    SHAREDCLIPBOARDPROVIDERFUNCMEMBER(OBJGETPATH, pfnObjGetPath);
 } SHAREDCLIPBOARDPROVIDERINTERFACE, *PSHAREDCLIPBOARDPROVIDERINTERFACE;
 
@@ -1032,11 +1162,12 @@
     /** The transfer's state (for SSM, later). */
     SHAREDCLIPBOARDURITRANSFERSTATE     State;
-    SHAREDCLIPBOARDURITRANSFEREVENTS    Events;
+    /** Events related to this transfer. */
+    SharedClipboardURITransferEventMap *pMapEvents;
+    SharedClipboardURIListMap          *pMapLists;
+    SharedClipboardURIObjMap           *pMapObj;
     /** The transfer's own (local) area, if any (can be NULL if not needed).
      *  The area itself has a clipboard area ID assigned.
      *  On the host this area ID gets shared (maintained / locked) across all VMs via VBoxSVC. */
     SharedClipboardArea                *pArea;
-    /** The URI list for this transfer. */
-    SharedClipboardURIList             *pURIList;
     SHAREDCLIPBOARDPROVIDERCTX          ProviderCtx;
     /** The transfer's provider interface. */
@@ -1082,24 +1213,25 @@
 int SharedClipboardURITransferClose(PSHAREDCLIPBOARDURITRANSFER pTransfer);
 
-int SharedClipboardURITransferListOpen(PSHAREDCLIPBOARDURITRANSFER pTransfer, PVBOXCLIPBOARDLISTHDR pListHdr,
-                                       PVBOXCLIPBOARDLISTHANDLE phList);
-int SharedClipboardURITransferListClose(PSHAREDCLIPBOARDURITRANSFER pTransfer, VBOXCLIPBOARDLISTHANDLE hList);
-int SharedClipboardURITransferListRead(PSHAREDCLIPBOARDURITRANSFER pTransfer, VBOXCLIPBOARDLISTHANDLE hList,
+int SharedClipboardURITransferListOpen(PSHAREDCLIPBOARDURITRANSFER pTransfer, PVBOXCLIPBOARDLISTOPENPARMS pOpenParms,
+                                       PSHAREDCLIPBOARDLISTHANDLE phList);
+int SharedClipboardURITransferListClose(PSHAREDCLIPBOARDURITRANSFER pTransfer, SHAREDCLIPBOARDLISTHANDLE hList);
+int SharedClipboardURITransferListGetHeader(PSHAREDCLIPBOARDURITRANSFER pTransfer, SHAREDCLIPBOARDLISTHANDLE hList,
+                                            PVBOXCLIPBOARDLISTHDR pHdr);
+PSHAREDCLIPBOARDURITRANSFEROBJ SharedClipboardURITransferListGetObj(PSHAREDCLIPBOARDURITRANSFER pTransfer,
+                                                                    SHAREDCLIPBOARDLISTHANDLE hList, uint64_t uIdx);
+int SharedClipboardURITransferListRead(PSHAREDCLIPBOARDURITRANSFER pTransfer, SHAREDCLIPBOARDLISTHANDLE hList,
                                        PVBOXCLIPBOARDLISTENTRY pEntry);
-int SharedClipboardURITransferListWrite(PSHAREDCLIPBOARDURITRANSFER pTransfer, VBOXCLIPBOARDLISTHANDLE hList,
+int SharedClipboardURITransferListWrite(PSHAREDCLIPBOARDURITRANSFER pTransfer, SHAREDCLIPBOARDLISTHANDLE hList,
                                         PVBOXCLIPBOARDLISTENTRY pEntry);
-bool SharedClipboardURITransferListHandleIsValid(PSHAREDCLIPBOARDURITRANSFER pTransfer, VBOXCLIPBOARDLISTHANDLE hList);
+bool SharedClipboardURITransferListHandleIsValid(PSHAREDCLIPBOARDURITRANSFER pTransfer, SHAREDCLIPBOARDLISTHANDLE hList);
 
 int SharedClipboardURITransferPrepare(PSHAREDCLIPBOARDURITRANSFER pTransfer);
-int SharedClipboardURITransferProviderCreate(PSHAREDCLIPBOARDURITRANSFER pTransfer,
-                                             PSHAREDCLIPBOARDPROVIDERCREATIONCTX pCreationCtx);
+int SharedClipboardURITransferSetInterface(PSHAREDCLIPBOARDURITRANSFER pTransfer,
+                                           PSHAREDCLIPBOARDPROVIDERCREATIONCTX pCreationCtx);
 void SharedClipboardURITransferReset(PSHAREDCLIPBOARDURITRANSFER pTransfer);
 SharedClipboardArea *SharedClipboardURITransferGetArea(PSHAREDCLIPBOARDURITRANSFER pTransfer);
-PSHAREDCLIPBOARDCLIENTURIOBJCTX SharedClipboardURITransferGetCurrentObjCtx(PSHAREDCLIPBOARDURITRANSFER pTransfer);
-const SharedClipboardURIObject *SharedClipboardURITransferGetCurrentObject(PSHAREDCLIPBOARDURITRANSFER pTransfer);
-SharedClipboardURIList *SharedClipboardURITransferGetList(PSHAREDCLIPBOARDURITRANSFER pTransfer);
-SharedClipboardURIObject *SharedClipboardURITransferGetObject(PSHAREDCLIPBOARDURITRANSFER pTransfer, uint64_t uIdx);
 SHAREDCLIPBOARDSOURCE SharedClipboardURITransferGetSource(PSHAREDCLIPBOARDURITRANSFER pTransfer);
 SHAREDCLIPBOARDURITRANSFERSTATUS SharedClipboardURITransferGetStatus(PSHAREDCLIPBOARDURITRANSFER pTransfer);
+int SharedClipboardURITransferHandleReply(PSHAREDCLIPBOARDURITRANSFER pTransfer, PVBOXCLIPBOARDREPLY pReply);
 int SharedClipboardURITransferRun(PSHAREDCLIPBOARDURITRANSFER pTransfer, PFNRTTHREAD pfnThreadFunc, void *pvUser);
 void SharedClipboardURITransferSetCallbacks(PSHAREDCLIPBOARDURITRANSFER pTransfer,
Index: /trunk/include/VBox/GuestHost/SharedClipboard-win.h
===================================================================
--- /trunk/include/VBox/GuestHost/SharedClipboard-win.h	(revision 79629)
+++ /trunk/include/VBox/GuestHost/SharedClipboard-win.h	(revision 79630)
@@ -287,5 +287,5 @@
 
     VBoxClipboardWinStreamImpl(VBoxClipboardWinDataObject *pParent,
-                               PSHAREDCLIPBOARDURITRANSFER pTransfer, uint64_t uObjIdx);
+                               PSHAREDCLIPBOARDURITRANSFER pTransfer, SHAREDCLIPBOARDOBJHANDLE hObj);
     virtual ~VBoxClipboardWinStreamImpl(void);
 
@@ -318,11 +318,11 @@
 
     /** Pointer to the parent data object. */
-    VBoxClipboardWinDataObject *m_pParent;
+    VBoxClipboardWinDataObject    *m_pParent;
     /** The stream object's current reference count. */
-    LONG                        m_lRefCount;
-    /** Pointer to the associated URI transfer object. */
-    PSHAREDCLIPBOARDURITRANSFER m_pURITransfer;
-    /** Index of the object to handle within the associated URI transfer object. */
-    uint64_t                    m_uObjIdx;
+    LONG                           m_lRefCount;
+    /** Pointer to the associated URI transfer. */
+    PSHAREDCLIPBOARDURITRANSFER    m_pURITransfer;
+    /** Handle to the associated URI object. */
+    SHAREDCLIPBOARDOBJHANDLE       m_hObj;
 };
 
Index: /trunk/include/VBox/GuestHost/SharedClipboard.h
===================================================================
--- /trunk/include/VBox/GuestHost/SharedClipboard.h	(revision 79629)
+++ /trunk/include/VBox/GuestHost/SharedClipboard.h	(revision 79630)
@@ -58,38 +58,4 @@
 #define VBOX_SHARED_CLIPBOARD_FMT_URI_LIST      UINT32_C(0x08)
 #endif
-
-/**
- * The host messages for the guest.
- */
-#define VBOX_SHARED_CLIPBOARD_HOST_MSG_QUIT                   1
-#define VBOX_SHARED_CLIPBOARD_HOST_MSG_READ_DATA              2
-#define VBOX_SHARED_CLIPBOARD_HOST_MSG_REPORT_FORMATS         3
-
-/** Initiates a new transfer (read / write) on the guest side. */
-#define VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_TRANSFER_START     4
-/** Open an URI list on the guest side. */
-#define VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_LIST_OPEN          5
-/** Closes a formerly opened URI list on the guest side. */
-#define VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_LIST_CLOSE         6
-/** Reads a list header from the guest. */
-#define VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_LIST_HDR_READ      7
-/** Writes a list header to the guest. */
-#define VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_LIST_HDR_WRITE     8
-/** Reads a list entry from the guest. */
-#define VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_LIST_ENTRY_READ    9
-/** Writes a list entry to the guest. */
-#define VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_LIST_ENTRY_WRITE   10
-/** Open an URI object on the guest side. */
-#define VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_OBJ_OPEN           11
-/** Closes a formerly opened URI object on the guest side. */
-#define VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_OBJ_CLOSE          12
-/** Reads from an object on the guest side. */
-#define VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_OBJ_READ           13
-/** Writes to an object on the guest side. */
-#define VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_OBJ_WRITE          14
-/** Indicates that the host has canceled a transfer. */
-#define VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_CANCEL             15
-/** Indicates that the an unrecoverable error on the host occurred . */
-#define VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_ERROR              16
 
 /**
Index: /trunk/include/VBox/HostServices/VBoxClipboardSvc.h
===================================================================
--- /trunk/include/VBox/HostServices/VBoxClipboardSvc.h	(revision 79629)
+++ /trunk/include/VBox/HostServices/VBoxClipboardSvc.h	(revision 79630)
@@ -66,4 +66,38 @@
 #define VBOX_SHARED_CLIPBOARD_HOST_FN_AREA_DETACH        8
 
+/**
+ * The host messages for the guest.
+ */
+#define VBOX_SHARED_CLIPBOARD_HOST_MSG_QUIT                   1
+#define VBOX_SHARED_CLIPBOARD_HOST_MSG_READ_DATA              2
+#define VBOX_SHARED_CLIPBOARD_HOST_MSG_REPORT_FORMATS         3
+
+/** Initiates a new transfer (read / write) on the guest side. */
+#define VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_TRANSFER_START     50
+/** Open an URI list on the guest side. */
+#define VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_LIST_OPEN          51
+/** Closes a formerly opened URI list on the guest side. */
+#define VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_LIST_CLOSE         52
+/** Reads a list header from the guest. */
+#define VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_LIST_HDR_READ      53
+/** Writes a list header to the guest. */
+#define VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_LIST_HDR_WRITE     54
+/** Reads a list entry from the guest. */
+#define VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_LIST_ENTRY_READ    55
+/** Writes a list entry to the guest. */
+#define VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_LIST_ENTRY_WRITE   56
+/** Open an URI object on the guest side. */
+#define VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_OBJ_OPEN           57
+/** Closes a formerly opened URI object on the guest side. */
+#define VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_OBJ_CLOSE          58
+/** Reads from an object on the guest side. */
+#define VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_OBJ_READ           59
+/** Writes to an object on the guest side. */
+#define VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_OBJ_WRITE          60
+/** Indicates that the host has canceled a transfer. */
+#define VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_CANCEL             61
+/** Indicates that the an unrecoverable error on the host occurred . */
+#define VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_ERROR              62
+
 /*
  * The service functions which are called by guest.
@@ -80,38 +114,114 @@
 #define VBOX_SHARED_CLIPBOARD_GUEST_FN_WRITE_DATA        4
 
-#define VBOX_SHARED_CLIPBOARD_GUEST_FN_TRANSFER_REPORT   5
-/** New message for getting the next message from the host (see VBOX_SHARED_CLIPBOARD_GUEST_FN_GET_HOST_MSG_OLD).
- *  New since URI handling was implemented. */
-#define VBOX_SHARED_CLIPBOARD_GUEST_FN_GET_HOST_MSG      6
+/** Peeks at the next message, returning immediately.
+ *  New since URI handling was implemented. */
+#define VBOX_SHARED_CLIPBOARD_GUEST_FN_MSG_PEEK_NOWAIT   5
+/** Peeks at the next message, waiting for one to arrive.
+ *  New since URI handling was implemented. */
+#define VBOX_SHARED_CLIPBOARD_GUEST_FN_MSG_PEEK_WAIT     6
+/** Gets the next message, returning immediately.
+ *  New since URI handling was implemented. */
+#define VBOX_SHARED_CLIPBOARD_GUEST_FN_MSG_GET           7
+/** Sends a transfer status to the host.
+ *  New since URI handling was implemented. */
+#define VBOX_SHARED_CLIPBOARD_GUEST_FN_STATUS            8
+/** Replies to a function from the host.
+ *  New since URI handling was implemented. */
+#define VBOX_SHARED_CLIPBOARD_GUEST_FN_REPLY             9
 /** Opens / gets a list handle from the host.
  *  New since URI handling was implemented. */
-#define VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_OPEN         7
+#define VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_OPEN         10
 /** Closes a list handle from the host.
  *  New since URI handling was implemented. */
-#define VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_CLOSE        8
+#define VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_CLOSE        11
 /** Reads a list header from the host.
  *  New since URI handling was implemented. */
-#define VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_HDR_READ     9
+#define VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_HDR_READ     12
 /** Writes a list header to the host.
  *  New since URI handling was implemented. */
-#define VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_HDR_WRITE    10
+#define VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_HDR_WRITE    13
 /** New since URI handling was implemented. */
-#define VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_ENTRY_READ   11
+#define VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_ENTRY_READ   14
 /** New since URI handling was implemented. */
-#define VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_ENTRY_WRITE  12
+#define VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_ENTRY_WRITE  15
 /** New since URI handling was implemented. */
-#define VBOX_SHARED_CLIPBOARD_GUEST_FN_OBJ_OPEN          13
+#define VBOX_SHARED_CLIPBOARD_GUEST_FN_OBJ_OPEN          16
 /** New since URI handling was implemented. */
-#define VBOX_SHARED_CLIPBOARD_GUEST_FN_OBJ_CLOSE         14
+#define VBOX_SHARED_CLIPBOARD_GUEST_FN_OBJ_CLOSE         17
 /** New since URI handling was implemented. */
-#define VBOX_SHARED_CLIPBOARD_GUEST_FN_OBJ_READ          15
+#define VBOX_SHARED_CLIPBOARD_GUEST_FN_OBJ_READ          18
 /**  New since URI handling was implemented. */
-#define VBOX_SHARED_CLIPBOARD_GUEST_FN_OBJ_WRITE         16
+#define VBOX_SHARED_CLIPBOARD_GUEST_FN_OBJ_WRITE         19
 /** Reports cancellation of the current operation to the host.
  *  New since URI handling was implemented. */
-#define VBOX_SHARED_CLIPBOARD_GUEST_FN_CANCEL            17
+#define VBOX_SHARED_CLIPBOARD_GUEST_FN_CANCEL            20
 /** Reports an error to the host.
  *  New since URI handling was implemented. */
-#define VBOX_SHARED_CLIPBOARD_GUEST_FN_ERROR             18
+#define VBOX_SHARED_CLIPBOARD_GUEST_FN_ERROR             21
+
+/**
+ * Translates a Shared Clipboard host message enum to a string.
+ *
+ * @returns Message ID string name.
+ * @param   uMsg                The message to translate.
+ */
+DECLINLINE(const char *) VBoxSvcClipboardHostMsgToStr(uint32_t uMsg)
+{
+    switch (uMsg)
+    {
+        RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_HOST_MSG_QUIT);
+        RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_HOST_MSG_READ_DATA);
+        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_LIST_OPEN);
+        RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_LIST_CLOSE);
+        RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_LIST_HDR_READ);
+        RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_LIST_HDR_WRITE);
+        RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_LIST_ENTRY_READ);
+        RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_LIST_ENTRY_WRITE);
+        RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_OBJ_OPEN);
+        RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_OBJ_CLOSE);
+        RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_OBJ_READ);
+        RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_OBJ_WRITE);
+        RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_CANCEL);
+        RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_ERROR);
+    }
+    return "Unknown";
+}
+
+/**
+ * Translates a Shared Clipboard guest message enum to a string.
+ *
+ * @returns Message ID string name.
+ * @param   uMsg                The message to translate.
+ */
+DECLINLINE(const char *) VBoxSvcClipboardGuestMsgToStr(uint32_t uMsg)
+{
+    switch (uMsg)
+    {
+        RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_GUEST_FN_REPORT_FORMATS);
+        RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_GUEST_FN_READ_DATA);
+        RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_GUEST_FN_WRITE_DATA);
+        RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_GUEST_FN_MSG_PEEK_NOWAIT);
+        RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_GUEST_FN_MSG_PEEK_WAIT);
+        RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_GUEST_FN_MSG_GET);
+        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_LIST_OPEN);
+        RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_CLOSE);
+        RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_HDR_READ);
+        RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_HDR_WRITE);
+        RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_ENTRY_READ);
+        RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_ENTRY_WRITE);
+        RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_GUEST_FN_OBJ_OPEN);
+        RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_GUEST_FN_OBJ_CLOSE);
+        RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_GUEST_FN_OBJ_READ);
+        RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_GUEST_FN_OBJ_WRITE);
+        RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_GUEST_FN_CANCEL);
+        RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_GUEST_FN_ERROR);
+        RT_CASE_RET_STR(VBOX_SHARED_CLIPBOARD_HOST_MSG_QUIT);
+    }
+    return "Unknown";
+}
 
 /** The maximum default chunk size for a single data transfer. */
@@ -201,12 +311,11 @@
     VBGLIOCHGCMCALL hdr;
 
-    /** Message ID. */
-    HGCMFunctionParameter uMsg;      /* OUT uint32_t */
-    /** Number of parameters the message needs. */
-    HGCMFunctionParameter cParms;    /* OUT uint32_t */
-    /** Whether or not to block (wait) for a
-     *  new message to arrive. */
-    HGCMFunctionParameter fBlock;    /* OUT uint32_t */
-} VBoxClipboardGetHostMsg;
+    /** uint32_t, out: Message ID. */
+    HGCMFunctionParameter uMsg;
+    /** uint32_t, out: Number of parameters the message needs. */
+    HGCMFunctionParameter cParms;
+    /** uint32_t, in: Whether or not to block (wait) for a  new message to arrive. */
+    HGCMFunctionParameter fBlock;
+} VBoxClipboardPeekMsg;
 
 #define VBOX_SHARED_CLIPBOARD_CPARMS_GET_HOST_MSG 3
@@ -217,13 +326,67 @@
 #define VBOX_SHAREDCLIPBOARD_LIST_FLAG_RESTART       RT_BIT(1)
 
-#define VBOX_SHAREDCLIPBOARD_INFO_FLAG_NONE         0
+#define VBOX_SHAREDCLIPBOARD_LISTHDR_FLAG_NONE       0
+
+#define VBOX_SHAREDCLIPBOARD_INFO_FLAG_NONE          0
 /** Get object information of type SHAREDCLIPBOARDFSOBJINFO. */
 #define VBOX_SHAREDCLIPBOARD_INFO_FLAG_FSOBJINFO     RT_BIT(0)
 
 /**
+ * Transfert status message.
+ */
+typedef struct _VBoxClipboardStatusMsg
+{
+    VBGLIOCHGCMCALL hdr;
+
+    /** uint32_t, in: Context ID. Unused at the moment. */
+    HGCMFunctionParameter uContext;
+    /** uint32_t, in: Transfer status of type SHAREDCLIPBOARDURITRANSFERSTATUS. */
+    HGCMFunctionParameter uStatus;
+    /** uint32_t, in: Size of payload of this status, based on the status type. */
+    HGCMFunctionParameter cbPayload;
+    /** pointer, in: Optional payload of this status, based on the status type. */
+    HGCMFunctionParameter pvPayload;
+} VBoxClipboardStatusMsg;
+
+#define VBOX_SHARED_CLIPBOARD_CPARMS_STATUS 4
+
+#define VBOX_SHAREDCLIPBOARD_REPLYMSGTYPE_INVALID           0
+#define VBOX_SHAREDCLIPBOARD_REPLYMSGTYPE_LIST_OPEN         1
+#define VBOX_SHAREDCLIPBOARD_REPLYMSGTYPE_OBJ_OPEN          2
+
+/**
+ * Generic reply message.
+ */
+typedef struct _VBoxClipboardReplyMsg
+{
+    VBGLIOCHGCMCALL hdr;
+
+    /** uint32_t, in: Context ID. Unused at the moment. */
+    HGCMFunctionParameter uContext;
+    /** uint32_t, in: Message type of type VBOX_SHAREDCLIPBOARD_REPLYMSGTYPE_XXX. */
+    HGCMFunctionParameter enmType;
+    /** uint32_t, in: IPRT result of overall operation. */
+    HGCMFunctionParameter rc;
+    /** uint32_t, in: 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. */
+    HGCMFunctionParameter pvPayload;
+    union
+    {
+        struct
+        {
+            HGCMFunctionParameter uHandle;
+        } ListOpen;
+        struct
+        {
+            HGCMFunctionParameter uHandle;
+        } ObjOpen;
+    } u;
+} VBoxClipboardReplyMsg;
+
+#define VBOX_SHARED_CLIPBOARD_CPARMS_REPLY_MIN 5
+
+/**
  * Opens a list.
- *
- * Used by:
- * VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_LIST_OPEN
  */
 typedef struct _VBoxClipboardListOpenMsg
@@ -231,25 +394,24 @@
     VBGLIOCHGCMCALL hdr;
 
-    /** uint32_t, in/out: Context ID. Unused at the moment. */
-    HGCMFunctionParameter uContext;
-    /** uint64_t, out: List handle. */
-    HGCMFunctionParameter uHandle;
-    /** uint32_t, in/out: Listing flags (see VBOX_SHAREDCLIPBOARD_LIST_FLAG_XXX). */
+    /** uint32_t, in: Context ID. Unused at the moment. */
+    HGCMFunctionParameter uContext;
+    /** uint32_t, in: Listing flags (see VBOX_SHAREDCLIPBOARD_LIST_FLAG_XXX). */
     HGCMFunctionParameter fList;
-    /** uint32_t, in/out: Feature flags (see VBOX_SHAREDCLIPBOARD_FEATURE_FLAG_XXX). */
-    HGCMFunctionParameter fFeatures;
     /** uint32_t, in: Size (in bytes) of the filter string. */
     HGCMFunctionParameter cbFilter;
     /** pointer, in: Filter string. */
     HGCMFunctionParameter pvFilter;
+    /** uint32_t, in: Size (in bytes) of the listing path. */
+    HGCMFunctionParameter cbPath;
+    /** pointer, in: Listing poth. If empty or NULL the listing's root path will be opened. */
+    HGCMFunctionParameter pvPath;
+    /** uint64_t, out: List handle. */
+    HGCMFunctionParameter uHandle;
 } VBoxClipboardListOpenMsg;
 
-#define VBOX_SHARED_CLIPBOARD_CPARMS_LIST_OPEN 5
+#define VBOX_SHARED_CLIPBOARD_CPARMS_LIST_OPEN 7
 
 /**
  * Closes a list.
- *
- * Used by:
- * VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_LIST_OPEN
  */
 typedef struct _VBoxClipboardListCloseMsg
@@ -265,58 +427,87 @@
 #define VBOX_SHARED_CLIPBOARD_CPARMS_LIST_CLOSE 2
 
-/**
- * Reads / writes a list header.
- *
- * Used by:
- * VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_LIST_HDR_READ
- * VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_LIST_HDR_WRITE
- */
-typedef struct _VBoxClipboardListHdrMsg
-{
-    VBGLIOCHGCMCALL hdr;
-
-    /** uint32_t, in/out: Context ID. Unused at the moment. */
+typedef struct _VBoxClipboardListHdrReqParms
+{
+    /** uint32_t, in: Context ID. Unused at the moment. */
     HGCMFunctionParameter uContext;
     /** uint64_t, in: List handle. */
     HGCMFunctionParameter uHandle;
-    /** value64, out:  Number of total objects to transfer. */
-    HGCMFunctionParameter cTotalObjects;
-    /** value64, out:  Number of total bytes to transfer. */
-    HGCMFunctionParameter cbTotalSize;
-    /** Compression type. */
-    HGCMFunctionParameter enmCompression;
-    /** Checksum type used for data transfer. */
-    HGCMFunctionParameter enmChecksumType;
-} VBoxClipboardListHdrReadMsg, VBoxClipboardListHdrWriteMsg;
-
-#define VBOX_SHARED_CLIPBOARD_CPARMS_LIST_HDR_READ  6
-#define VBOX_SHARED_CLIPBOARD_CPARMS_LIST_HDR_WRITE 6
-
-/**
- * Reads / writes a list entry.
- *
- * Used by:
- * VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_LIST_ENTRY_READ
- * VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_LIST_ENTRY_WRITE
- */
-typedef struct _VBoxClipboardListEntryMsg
-{
-    VBGLIOCHGCMCALL hdr;
-
-    /** Context ID. Unused at the moment. */
+    /** uint32_t, in: Flags of type VBOX_SHAREDCLIPBOARD_LISTHDR_FLAG_XXX. */
+    HGCMFunctionParameter fFlags;
+} VBoxClipboardListHdrReqParms;
+
+/**
+ * Request to read a list header.
+ */
+typedef struct _VBoxClipboardListHdrReadReqMsg
+{
+    VBGLIOCHGCMCALL hdr;
+
+    VBoxClipboardListHdrReqParms ReqParms;
+} VBoxClipboardListHdrReadReqMsg;
+
+#define VBOX_SHARED_CLIPBOARD_CPARMS_LIST_HDR_READ_REQ 3
+
+/**
+ * Reads / Writes a list header.
+ */
+typedef struct _VBoxClipboardListHdrMsg
+{
+    VBGLIOCHGCMCALL hdr;
+
+    VBoxClipboardListHdrReqParms ReqParms;
+    /** uint32_t, in/out: Feature flags (see VBOX_SHAREDCLIPBOARD_FEATURE_FLAG_XXX). */
+    HGCMFunctionParameter        fFeatures;
+    /** uint64_t, in/out:  Number of total objects to transfer. */
+    HGCMFunctionParameter        cTotalObjects;
+    /** uint64_t, in/out:  Number of total bytes to transfer. */
+    HGCMFunctionParameter        cbTotalSize;
+    /** uint32_t, in/out: Compression type. */
+    HGCMFunctionParameter        enmCompression;
+    /** uint32_t, in/out: Checksum type used for data transfer. */
+    HGCMFunctionParameter        enmChecksumType;
+} VBoxClipboardListHdrMsg;
+
+#define VBOX_SHARED_CLIPBOARD_CPARMS_LIST_HDR 8
+
+typedef struct _VBoxClipboardListEntryReqParms
+{
+    /** uint32_t, Context ID. Unused at the moment. */
     HGCMFunctionParameter uContext;
     /** uint64_t, in: List handle. */
     HGCMFunctionParameter uHandle;
-    /** uint32_t, in/out: VBOX_SHAREDCLIPBOARD_INFO_FLAG_XXX. */
+    /** uint32_t, in: VBOX_SHAREDCLIPBOARD_INFO_FLAG_XXX. */
     HGCMFunctionParameter fInfo;
-    /** uint32_t, in/out: Bytes to be used for information/How many bytes were used.  */
-    HGCMFunctionParameter cbInfo;
-    /** pointer, in/out: Information to be set/get (SHAREDCLIPBOARDFSOBJINFO only currently).
+} VBoxClipboardListEntryReqParms;
+
+/**
+ * Request to read a list entry.
+ */
+typedef struct _VBoxClipboardListEntryReadReqMsg
+{
+    VBGLIOCHGCMCALL hdr;
+
+    VBoxClipboardListEntryReqParms ReqParms;
+} VBoxClipboardListEntryReadReqMsg;
+
+#define VBOX_SHARED_CLIPBOARD_CPARMS_LIST_ENTRY_READ_REQ 3
+
+/**
+ * Reads / Writes a list entry.
+ */
+typedef struct _VBoxClipboardListEntryMsg
+{
+    VBGLIOCHGCMCALL hdr;
+
+    /** in: Request parameters. */
+    VBoxClipboardListEntryReqParms ReqParms;
+    /** 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).
      * Do not forget to set the SHAREDCLIPBOARDFSOBJINFO::Attr::enmAdditional for Get operation as well.  */
-    HGCMFunctionParameter pvInfo;
-} VBoxClipboardListEntryReadMsg, VBoxClipboardListEntryWriteMsg;
-
-#define VBOX_SHARED_CLIPBOARD_CPARMS_LIST_ENTRY_READ  5
-#define VBOX_SHARED_CLIPBOARD_CPARMS_LIST_ENTRY_WRITE 5
+    HGCMFunctionParameter          pvInfo;
+} VBoxClipboardListEntryMsg;
+
+#define VBOX_SHARED_CLIPBOARD_CPARMS_LIST_ENTRY 5
 
 typedef struct _VBoxClipboardObjOpenMsg
@@ -339,5 +530,5 @@
    VBGLIOCHGCMCALL hdr;
 
-    /** value64, in: SHAREDCLIPBOARDOBJHANDLE of object to close. */
+    /** uint64_t, in: SHAREDCLIPBOARDOBJHANDLE of object to close. */
     HGCMFunctionParameter uHandle;
 } VBoxClipboardObjCloseMsg;
@@ -358,5 +549,5 @@
     /** Context ID. Unused at the moment. */
     HGCMFunctionParameter uContext;     /* OUT uint32_t */
-    /** value64, in: SHAREDCLIPBOARDOBJHANDLE of object to write to. */
+    /** uint64_t, in: SHAREDCLIPBOARDOBJHANDLE of object to write to. */
     HGCMFunctionParameter uHandle;
     /** Size (in bytes) of current data chunk. */
@@ -416,7 +607,7 @@
 
 #ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
-int VBoxSvcClipboardURIGetListHdr(uint32_t cParms, VBOXHGCMSVCPARM paParms[], PVBOXCLIPBOARDLISTHANDLE phList, PVBOXCLIPBOARDLISTHDR pListHdr);
+int VBoxSvcClipboardURIGetListHdr(uint32_t cParms, VBOXHGCMSVCPARM paParms[], PSHAREDCLIPBOARDLISTHANDLE phList, PVBOXCLIPBOARDLISTHDR pListHdr);
 int VBoxSvcClipboardURISetListHdr(uint32_t cParms, VBOXHGCMSVCPARM paParms[], PVBOXCLIPBOARDLISTHDR pListHdr);
-int VBoxSvcClipboardURIGetListEntry(uint32_t cParms, VBOXHGCMSVCPARM paParms[], PVBOXCLIPBOARDLISTHANDLE phList, PVBOXCLIPBOARDLISTENTRY pListEntry);
+int VBoxSvcClipboardURIGetListEntry(uint32_t cParms, VBOXHGCMSVCPARM paParms[], PSHAREDCLIPBOARDLISTHANDLE phList, PVBOXCLIPBOARDLISTENTRY pListEntry);
 int VBoxSvcClipboardURISetListEntry(uint32_t cParms, VBOXHGCMSVCPARM paParms[], PVBOXCLIPBOARDLISTENTRY pListEntry);
 int VBoxSvcClipboardURIGetFileData(uint32_t cParms, VBOXHGCMSVCPARM paParms[], PVBOXCLIPBOARDFILEDATA pFileData);
Index: /trunk/include/VBox/VBoxGuestLib.h
===================================================================
--- /trunk/include/VBox/VBoxGuestLib.h	(revision 79629)
+++ /trunk/include/VBox/VBoxGuestLib.h	(revision 79630)
@@ -624,8 +624,16 @@
 VBGLR3DECL(void)    VbglR3ClipboardEventFree(PVBGLR3CLIPBOARDEVENT pEvent);
 
-VBGLR3DECL(int)     VbglR3ClipboardListHdrRead(HGCMCLIENTID idClient, PVBOXCLIPBOARDLISTHDR pListHdr);
-VBGLR3DECL(int)     VbglR3ClipboardSendListHdrWrite(HGCMCLIENTID idClient, VBOXCLIPBOARDLISTHANDLE hList, PVBOXCLIPBOARDLISTHDR pListHdr);
-VBGLR3DECL(int)     VbglR3ClipboardListEntryRead(HGCMCLIENTID idClient, PVBOXCLIPBOARDLISTENTRY pListEntry);
-VBGLR3DECL(int)     VbglR3ClipboardSendListEntryWrite(HGCMCLIENTID idClient, VBOXCLIPBOARDLISTHANDLE hList, PVBOXCLIPBOARDLISTENTRY pListEntry);
+VBGLR3DECL(int)     VbglR3ClipboardTransferSendStatus(HGCMCLIENTID idClient, SHAREDCLIPBOARDURITRANSFERSTATUS uStatus);
+
+VBGLR3DECL(int)     VbglR3ClipboardListOpenSend(HGCMCLIENTID idClient, PVBOXCLIPBOARDLISTOPENPARMS pOpenParms, PSHAREDCLIPBOARDLISTHANDLE phList);
+VBGLR3DECL(int)     VbglR3ClipboardListOpenRecv(HGCMCLIENTID idClient, PVBOXCLIPBOARDLISTOPENPARMS pOpenParms);
+VBGLR3DECL(int)     VbglR3ClipboardListOpenReply(HGCMCLIENTID idClient, int rcReply, SHAREDCLIPBOARDLISTHANDLE hList);
+
+VBGLR3DECL(int)     VbglR3ClipboardListCloseSend(HGCMCLIENTID idClient, SHAREDCLIPBOARDLISTHANDLE hList);
+VBGLR3DECL(int)     VbglR3ClipboardListCloseRecv(HGCMCLIENTID idClient, PSHAREDCLIPBOARDLISTHANDLE phList);
+
+VBGLR3DECL(int)     VbglR3ClipboardListHdrWrite(HGCMCLIENTID idClient, SHAREDCLIPBOARDLISTHANDLE hList, PVBOXCLIPBOARDLISTHDR pListHdr);
+
+VBGLR3DECL(int)     VbglR3ClipboardListEntryWrite(HGCMCLIENTID idClient, SHAREDCLIPBOARDLISTHANDLE hList, PVBOXCLIPBOARDLISTENTRY pListEntry);
 
 VBGLR3DECL(int)     VbglR3ClipboardObjOpen(HGCMCLIENTID idClient,
Index: /trunk/include/VBox/err.h
===================================================================
--- /trunk/include/VBox/err.h	(revision 79629)
+++ /trunk/include/VBox/err.h	(revision 79630)
@@ -2921,4 +2921,10 @@
 /** Maximum of concurrent clipboard transfers has been reached. */
 #define VERR_SHCLPB_MAX_TRANSFERS_REACHED           (-7100)
+/** Maximum number of Shared Clipboard objects has been reached. */
+#define VERR_SHCLPB_MAX_OBJECTS_REACHED             (-7101)
+/** A Shared Clipboard list handle is invalid. */
+#define VERR_SHCLPB_LIST_HANDLE_INVALID             (-7102)
+/** A Shared Clipboard objects handle is invalid. */
+#define VERR_SHCLPB_OBJ_HANDLE_INVALID              (-7103)
 /** @} */
 /* SED-END */
Index: /trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxClipboard.cpp
===================================================================
--- /trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxClipboard.cpp	(revision 79629)
+++ /trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxClipboard.cpp	(revision 79630)
@@ -70,4 +70,10 @@
 
 #ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
+typedef struct _VBOXCLIPBOARDURIREADTHREADCTX
+{
+    PVBOXCLIPBOARDCONTEXT       pClipboardCtx;
+    PSHAREDCLIPBOARDURITRANSFER pTransfer;
+} VBOXCLIPBOARDURIREADTHREADCTX, *PVBOXCLIPBOARDURIREADTHREADCTX;
+
 typedef struct _VBOXCLIPBOARDURIWRITETHREADCTX
 {
@@ -108,4 +114,9 @@
     AssertPtr(pCtx);
 
+    PSHAREDCLIPBOARDURITRANSFER pTransfer = pCtx->pTransfer;
+    AssertPtr(pTransfer);
+
+    pTransfer->Thread.fStarted = true;
+
     RTThreadUserSignal(RTThreadSelf());
 
@@ -114,15 +125,5 @@
     if (RT_SUCCESS(rc))
     {
-        VBoxClipboardTransferReport Msg;
-        RT_ZERO(Msg);
-
-        VBGL_HGCM_HDR_INIT(&Msg.hdr, uClientID,
-                            VBOX_SHARED_CLIPBOARD_GUEST_FN_TRANSFER_REPORT, VBOX_SHARED_CLIPBOARD_CPARMS_TRANSFER_REPORT);
-
-        Msg.uContext.SetUInt32(0);
-        Msg.uStatus.SetUInt32(0);
-
-        rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
-
+        rc = VbglR3ClipboardTransferSendStatus(uClientID, SHAREDCLIPBOARDURITRANSFERSTATUS_RUNNING);
         if (RT_SUCCESS(rc))
         {
@@ -132,54 +133,11 @@
             for (;;)
             {
-                PVBGLR3CLIPBOARDEVENT pEvent;
-                rc = VbglR3ClipboardEventGetNext(uClientID, pCtx->pTransfer, &pEvent);
+                PVBGLR3CLIPBOARDEVENT pEvent = NULL;
+                rc = VbglR3ClipboardEventGetNext(uClientID, pTransfer, &pEvent);
                 if (RT_SUCCESS(rc))
                 {
-                   switch (pEvent->enmType)
-                   {
-                       case VBGLR3CLIPBOARDEVENTTYPE_URI_LIST_HDR_READ:
-                       {
-                           LogFlowFunc(("VBGLR3CLIPBOARDEVENTTYPE_URI_READ_LIST_HDR\n"));
-                           break;
-                       }
-
-                       case VBGLR3CLIPBOARDEVENTTYPE_URI_LIST_ENTRY_READ:
-                       {
-                           LogFlowFunc(("VBGLR3CLIPBOARDEVENTTYPE_URI_READ_LIST_ENTRY\n"));
-                           break;
-                       }
-
-                       case VBGLR3CLIPBOARDEVENTTYPE_URI_OBJ_OPEN:
-                       {
-                           LogFlowFunc(("VBGLR3CLIPBOARDEVENTTYPE_URI_OBJ_OPEN\n"));
-                           break;
-                       }
-
-                       case VBGLR3CLIPBOARDEVENTTYPE_URI_OBJ_CLOSE:
-                       {
-                           LogFlowFunc(("VBGLR3CLIPBOARDEVENTTYPE_URI_OBJ_CLOSE\n"));
-                           break;
-                       }
-
-                       case VBGLR3CLIPBOARDEVENTTYPE_URI_OBJ_READ:
-                       {
-                           LogFlowFunc(("VBGLR3CLIPBOARDEVENTTYPE_URI_OBJ_READ\n"));
-                           break;
-                       }
-
-                       case VBGLR3CLIPBOARDEVENTTYPE_URI_CANCEL:
-                           RT_FALL_THROUGH();
-                       case VBGLR3CLIPBOARDEVENTTYPE_URI_ERROR:
-                           LogFlowFunc(("VBGLR3CLIPBOARDEVENTTYPE_URI_CANCEL / ERROR\n"));
-                           fTerminate = true;
-                           break;
-
-                       default:
-                           rc = VERR_NOT_SUPPORTED;
-                           cErrors++;
-                           break;
-                   }
-
-                   VbglR3ClipboardEventFree(pEvent);
+                    /* Nothing to do in here right now. */
+
+                    VbglR3ClipboardEventFree(pEvent);
                 }
 
@@ -272,8 +230,8 @@
 }
 
-static int vboxClipboardURIListHdrRead(PSHAREDCLIPBOARDPROVIDERCTX pCtx, VBOXCLIPBOARDLISTHANDLE hList,
-                                       PVBOXCLIPBOARDLISTHDR pListHdr)
-{
-    RT_NOREF(hList);
+static int vboxClipboardURIListOpen(PSHAREDCLIPBOARDPROVIDERCTX pCtx, PVBOXCLIPBOARDLISTHDR pListHdr,
+                                    PSHAREDCLIPBOARDLISTHANDLE phList)
+{
+    RT_NOREF(pCtx, pListHdr, phList);
 
     LogFlowFuncEnter();
@@ -282,8 +240,5 @@
     AssertPtr(pThisCtx);
 
-    LogFlowFunc(("c=%RU32\n", pThisCtx->u32ClientID));
-
-    RT_NOREF(pListHdr);
-    int rc = 0; //VbglR3ClipboardListHdrRead(pThisCtx->u32ClientID, pListHdr);
+    int rc = 0; // VbglR3ClipboardRecvListOpen(pThisCtx->u32ClientID, pListHdr, phList);
 
     LogFlowFuncLeaveRC(rc);
@@ -291,7 +246,9 @@
 }
 
-static int vboxClipboardURIListHdrWrite(PSHAREDCLIPBOARDPROVIDERCTX pCtx, VBOXCLIPBOARDLISTHANDLE hList,
-                                        PVBOXCLIPBOARDLISTHDR pListHdr)
-{
+static int vboxClipboardURIListHdrRead(PSHAREDCLIPBOARDPROVIDERCTX pCtx, SHAREDCLIPBOARDLISTHANDLE hList,
+                                       PVBOXCLIPBOARDLISTHDR pListHdr)
+{
+    RT_NOREF(hList);
+
     LogFlowFuncEnter();
 
@@ -299,5 +256,16 @@
     AssertPtr(pThisCtx);
 
-    int rc = VbglR3ClipboardSendListHdrWrite(pThisCtx->u32ClientID, hList, pListHdr);
+    LogFlowFunc(("c=%RU32\n", pThisCtx->u32ClientID));
+
+    int rc = SharedClipboardURIListHdrInit(pListHdr);
+    if (RT_SUCCESS(rc))
+    {
+        if (RT_SUCCESS(rc))
+        {
+            //rc = VbglR3ClipboardListHdrReadRecv(pThisCtx->u32ClientID, hList, pListHdr);
+        }
+        else
+            SharedClipboardURIListHdrDestroy(pListHdr);
+    }
 
     LogFlowFuncLeaveRC(rc);
@@ -305,9 +273,8 @@
 }
 
-static int vboxClipboardURIListEntryRead(PSHAREDCLIPBOARDPROVIDERCTX pCtx, VBOXCLIPBOARDLISTHANDLE hList,
-                                         PVBOXCLIPBOARDLISTENTRY pListEntry)
-{
-    RT_NOREF(hList);
-
+/*
+static int vboxClipboardURIListHdrWrite(PSHAREDCLIPBOARDPROVIDERCTX pCtx, SHAREDCLIPBOARDLISTHANDLE hList,
+                                        PVBOXCLIPBOARDLISTHDR pListHdr)
+{
     LogFlowFuncEnter();
 
@@ -315,4 +282,20 @@
     AssertPtr(pThisCtx);
 
+    int rc = VbglR3ClipboardListHdrWrite(pThisCtx->u32ClientID, hList, pListHdr);
+
+    LogFlowFuncLeaveRC(rc);
+    return rc;
+}*/
+
+static int vboxClipboardURIListEntryRead(PSHAREDCLIPBOARDPROVIDERCTX pCtx, SHAREDCLIPBOARDLISTHANDLE hList,
+                                         PVBOXCLIPBOARDLISTENTRY pListEntry)
+{
+    RT_NOREF(hList);
+
+    LogFlowFuncEnter();
+
+    PVBOXCLIPBOARDCONTEXT pThisCtx = (PVBOXCLIPBOARDCONTEXT)pCtx->pvUser;
+    AssertPtr(pThisCtx);
+
     RT_NOREF(pListEntry);
     int rc = 0; // VbglR3ClipboardListEntryRead(pThisCtx->u32ClientID, pListEntry);
@@ -322,5 +305,6 @@
 }
 
-static int vboxClipboardURIListEntryWrite(PSHAREDCLIPBOARDPROVIDERCTX pCtx, VBOXCLIPBOARDLISTHANDLE hList,
+/*
+static int vboxClipboardURIListEntryWrite(PSHAREDCLIPBOARDPROVIDERCTX pCtx, SHAREDCLIPBOARDLISTHANDLE hList,
                                           PVBOXCLIPBOARDLISTENTRY pListEntry)
 {
@@ -330,9 +314,10 @@
     AssertPtr(pThisCtx);
 
-    int rc = VbglR3ClipboardSendListEntryWrite(pThisCtx->u32ClientID, hList, pListEntry);
+    int rc = VbglR3ClipboardListEntryWrite(pThisCtx->u32ClientID, hList, pListEntry);
 
     LogFlowFuncLeaveRC(rc);
     return rc;
 }
+*/
 
 static int vboxClipboardURIObjOpen(PSHAREDCLIPBOARDPROVIDERCTX pCtx, const char *pszPath,
@@ -636,5 +621,5 @@
                    VBoxClipboardWinClear();
 
-#ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
+#if 0
                    if (fFormats & VBOX_SHARED_CLIPBOARD_FMT_URI_LIST)
                    {
@@ -671,5 +656,5 @@
                            creationCtx.pvUser = pCtx;
 
-                           rc = SharedClipboardURITransferProviderCreate(pTransfer, &creationCtx);
+                           rc = SharedClipboardURITransferSetInterface(pTransfer, &creationCtx);
                            if (RT_SUCCESS(rc))
                            {
@@ -690,5 +675,5 @@
 
                        VBoxClipboardWinClose();
-#ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
+#if 0
                    }
 #endif
@@ -802,4 +787,5 @@
                if (RT_SUCCESS(rc))
                {
+            #if 0
                    SHAREDCLIPBOARDURITRANSFERCALLBACKS TransferCallbacks;
                    RT_ZERO(TransferCallbacks);
@@ -824,7 +810,8 @@
                    creationCtx.pvUser = pCtx;
 
-                   rc = SharedClipboardURITransferProviderCreate(pTransfer, &creationCtx);
+                   rc = SharedClipboardURITransferSetInterface(pTransfer, &creationCtx);
                    if (RT_SUCCESS(rc))
                    {
+            #endif
                        rc = SharedClipboardURICtxTransferAdd(&pCtx->URI, pTransfer);
                        if (RT_SUCCESS(rc))
@@ -880,5 +867,5 @@
                            }
                        }
-                   }
+                   //}
                }
 
@@ -891,8 +878,55 @@
        }
 
+       /* The host wants to write URI data. */
        case VBOX_CLIPBOARD_WM_URI_START_WRITE:
        {
            LogFunc(("VBOX_CLIPBOARD_WM_URI_START_WRITE: cTransfersRunning=%RU32\n",
                     SharedClipboardURICtxGetRunningTransfers(&pCtx->URI)));
+
+           PSHAREDCLIPBOARDURITRANSFER pTransfer;
+           int rc = SharedClipboardURITransferCreate(SHAREDCLIPBOARDURITRANSFERDIR_READ,
+                                                     SHAREDCLIPBOARDSOURCE_LOCAL,
+                                                     &pTransfer);
+           if (RT_SUCCESS(rc))
+           {
+               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_REMOTE;
+
+               RT_ZERO(creationCtx.Interface);
+               creationCtx.Interface.pfnListHdrRead   = vboxClipboardURIListHdrRead;
+               creationCtx.Interface.pfnListEntryRead = vboxClipboardURIListEntryRead;
+               creationCtx.Interface.pfnObjOpen       = vboxClipboardURIObjOpen;
+               creationCtx.Interface.pfnObjClose      = vboxClipboardURIObjClose;
+               creationCtx.Interface.pfnObjRead       = vboxClipboardURIObjRead;
+
+               creationCtx.pvUser = pCtx;
+
+               rc = SharedClipboardURITransferSetInterface(pTransfer, &creationCtx);
+               if (RT_SUCCESS(rc))
+               {
+                   rc = SharedClipboardURICtxTransferAdd(&pCtx->URI, pTransfer);
+                   if (RT_SUCCESS(rc))
+                   {
+                       if (RT_SUCCESS(rc))
+                       {
+                           rc = SharedClipboardURITransferPrepare(pTransfer);
+                           if (RT_SUCCESS(rc))
+                           {
+                               rc = VBoxClipboardWinURITransferCreate(pWinCtx, pTransfer);
+                           }
+                       }
+                   }
+               }
+           }
 
            break;
Index: /trunk/src/VBox/Additions/common/VBoxGuest/lib/VBoxGuestR3LibClipboard.cpp
===================================================================
--- /trunk/src/VBox/Additions/common/VBoxGuest/lib/VBoxGuestR3LibClipboard.cpp	(revision 79629)
+++ /trunk/src/VBox/Additions/common/VBoxGuest/lib/VBoxGuestR3LibClipboard.cpp	(revision 79630)
@@ -162,10 +162,11 @@
 
 #ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
-static int vbglR3ClipboardGetNextMsgType(HGCMCLIENTID idClient, uint32_t *puMsg, uint32_t *pcParms, bool fWait)
+#if 0
+static int vbglR3ClipboardPeekMsg(HGCMCLIENTID idClient, uint32_t *puMsg, uint32_t *pcParms, bool fWait)
 {
     AssertPtrReturn(puMsg,   VERR_INVALID_POINTER);
     AssertPtrReturn(pcParms, VERR_INVALID_POINTER);
 
-    VBoxClipboardGetHostMsg Msg;
+    VBoxClipboardPeekMsg Msg;
     RT_ZERO(Msg);
 
@@ -188,69 +189,233 @@
     return rc;
 }
-
-static int vbglR3ClipboardRecvListOpen(HGCMCLIENTID idClient, PVBOXCLIPBOARDLISTHDR pListHdr)
+#else
+/**
+ * Peeks at the next host message, waiting for one to turn up.
+ *
+ * @returns VBox status code.
+ * @retval  VERR_INTERRUPTED if interrupted.  Does the necessary cleanup, so
+ *          caller just have to repeat this call.
+ * @retval  VERR_VM_RESTORED if the VM has been restored (idRestoreCheck).
+ *
+ * @param   idClient        The client ID returned by VbglR3GuestCtrlConnect().
+ * @param   pidMsg          Where to store the message id.
+ * @param   pcParameters    Where to store the number  of parameters which will
+ *                          be received in a second call to the host.
+ * @param   pidRestoreCheck Pointer to the VbglR3GetSessionId() variable to use
+ *                          for the VM restore check.  Optional.
+ *
+ * @note    Restore check is only performed optimally with a 6.0 host.
+ */
+static int vbglR3ClipboardMsgPeekWait(uint32_t idClient, uint32_t *pidMsg, uint32_t *pcParameters, uint64_t *pidRestoreCheck)
+{
+    AssertPtrReturn(pidMsg, VERR_INVALID_POINTER);
+    AssertPtrReturn(pcParameters, VERR_INVALID_POINTER);
+
+    int rc;
+
+    struct
+    {
+        VBGLIOCHGCMCALL Hdr;
+        HGCMFunctionParameter idMsg;       /* Doubles as restore check on input. */
+        HGCMFunctionParameter cParameters;
+    } Msg;
+    VBGL_HGCM_HDR_INIT(&Msg.Hdr, idClient, VBOX_SHARED_CLIPBOARD_GUEST_FN_MSG_PEEK_WAIT, 2);
+    VbglHGCMParmUInt64Set(&Msg.idMsg, pidRestoreCheck ? *pidRestoreCheck : 0);
+    VbglHGCMParmUInt32Set(&Msg.cParameters, 0);
+    rc = VbglR3HGCMCall(&Msg.Hdr, sizeof(Msg));
+    LogRel2(("VbglR3GuestCtrlMsgPeekWait -> %Rrc\n", rc));
+    if (RT_SUCCESS(rc))
+    {
+        AssertMsgReturn(   Msg.idMsg.type       == VMMDevHGCMParmType_64bit
+                        && Msg.cParameters.type == VMMDevHGCMParmType_32bit,
+                        ("msg.type=%d num_parms.type=%d\n", Msg.idMsg.type, Msg.cParameters.type),
+                        VERR_INTERNAL_ERROR_3);
+
+        *pidMsg       = (uint32_t)Msg.idMsg.u.value64;
+        *pcParameters = Msg.cParameters.u.value32;
+        return rc;
+    }
+
+    /*
+     * If interrupted we must cancel the call so it doesn't prevent us from making another one.
+     */
+    if (rc == VERR_INTERRUPTED)
+    {
+        VBGL_HGCM_HDR_INIT(&Msg.Hdr, idClient, VBOX_SHARED_CLIPBOARD_GUEST_FN_CANCEL, 0);
+        int rc2 = VbglR3HGCMCall(&Msg.Hdr, sizeof(Msg.Hdr));
+        AssertRC(rc2);
+    }
+
+    /*
+     * If restored, update pidRestoreCheck.
+     */
+    if (rc == VERR_VM_RESTORED && pidRestoreCheck)
+        *pidRestoreCheck = Msg.idMsg.u.value64;
+
+    *pidMsg       = UINT32_MAX - 1;
+    *pcParameters = UINT32_MAX - 2;
+    return rc;
+}
+#endif
+
+VBGLR3DECL(int) VbglR3ClipboardTransferSendStatus(HGCMCLIENTID idClient, SHAREDCLIPBOARDURITRANSFERSTATUS uStatus)
+{
+    VBoxClipboardStatusMsg Msg;
+    RT_ZERO(Msg);
+
+    VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient,
+                       VBOX_SHARED_CLIPBOARD_GUEST_FN_STATUS, VBOX_SHARED_CLIPBOARD_CPARMS_STATUS);
+
+    Msg.uContext.SetUInt32(0); /** @todo Context ID not used yet. */
+    Msg.uStatus.SetUInt32(uStatus);
+    Msg.cbPayload.SetUInt32(0);
+    Msg.pvPayload.SetPtr(NULL, 0);
+
+    int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
+
+    LogFlowFuncLeaveRC(rc);
+    return rc;
+}
+
+VBGLR3DECL(int) VbglR3ClipboardListOpenSend(HGCMCLIENTID idClient, PVBOXCLIPBOARDLISTOPENPARMS pOpenParms,
+                                            PSHAREDCLIPBOARDLISTHANDLE phList)
+{
+    AssertPtrReturn(pOpenParms, VERR_INVALID_POINTER);
+    AssertPtrReturn(phList,     VERR_INVALID_POINTER);
+
+    VBoxClipboardListOpenMsg Msg;
+    RT_ZERO(Msg);
+
+    VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient,
+                       VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_OPEN, VBOX_SHARED_CLIPBOARD_CPARMS_LIST_OPEN);
+
+    Msg.uContext.SetUInt32(0); /** @todo Context ID not used yet. */
+    Msg.fList.SetUInt32(0);
+    Msg.cbFilter.SetUInt32(pOpenParms->cbFilter);
+    Msg.pvFilter.SetPtr(pOpenParms->pszFilter, pOpenParms->cbFilter);
+    Msg.cbPath.SetUInt32(pOpenParms->cbPath);
+    Msg.pvFilter.SetPtr(pOpenParms->pszPath, pOpenParms->cbPath);
+
+    int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
+    if (RT_SUCCESS(rc))
+    {
+        rc = Msg.uHandle.GetUInt64(phList); AssertRC(rc);
+    }
+
+    LogFlowFuncLeaveRC(rc);
+    return rc;
+}
+
+VBGLR3DECL(int) VbglR3ClipboardListOpenRecv(HGCMCLIENTID idClient, PVBOXCLIPBOARDLISTOPENPARMS pOpenParms)
+{
+    AssertPtrReturn(pOpenParms, VERR_INVALID_POINTER);
+
+    VBoxClipboardListOpenMsg Msg;
+    RT_ZERO(Msg);
+
+    VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient,
+                       VBOX_SHARED_CLIPBOARD_GUEST_FN_MSG_GET, VBOX_SHARED_CLIPBOARD_CPARMS_LIST_OPEN);
+
+    Msg.uContext.SetUInt32(VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_LIST_OPEN);
+    Msg.fList.SetUInt32(0);
+    Msg.cbPath.SetUInt32(pOpenParms->cbPath);
+    Msg.pvPath.SetPtr(pOpenParms->pszPath, pOpenParms->cbPath);
+    Msg.cbFilter.SetUInt32(pOpenParms->cbFilter);
+    Msg.pvFilter.SetPtr(pOpenParms->pszFilter, pOpenParms->cbFilter);
+    Msg.uHandle.SetUInt64(0);
+
+    int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
+    if (RT_SUCCESS(rc))
+    {
+        rc = Msg.fList.GetUInt32(&pOpenParms->fList);
+        if (RT_SUCCESS(rc))
+            rc = Msg.cbFilter.GetUInt32(&pOpenParms->cbFilter);
+        if (RT_SUCCESS(rc))
+            rc = Msg.cbPath.GetUInt32(&pOpenParms->cbPath);
+    }
+
+    LogFlowFuncLeaveRC(rc);
+    return rc;
+}
+
+VBGLR3DECL(int) VbglR3ClipboardListOpenReply(HGCMCLIENTID idClient, int rcReply, SHAREDCLIPBOARDLISTHANDLE hList)
+{
+    VBoxClipboardReplyMsg Msg;
+    RT_ZERO(Msg);
+
+    VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient,
+                       VBOX_SHARED_CLIPBOARD_GUEST_FN_REPLY, 6);
+
+    Msg.uContext.SetUInt32(0); /** @todo Context ID not used yet. */
+    Msg.enmType.SetUInt32(VBOX_SHAREDCLIPBOARD_REPLYMSGTYPE_LIST_OPEN);
+    Msg.rc.SetUInt32((uint32_t)rcReply); /** int vs. uint32_t */
+    Msg.cbPayload.SetUInt32(0);
+    Msg.pvPayload.SetPtr(0, NULL);
+
+    Msg.u.ListOpen.uHandle.SetUInt64(hList);
+
+    int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
+
+    LogFlowFuncLeaveRC(rc);
+    return rc;
+}
+
+VBGLR3DECL(int) VbglR3ClipboardListCloseSend(HGCMCLIENTID idClient, SHAREDCLIPBOARDLISTHANDLE hList)
+{
+    VBoxClipboardListCloseMsg Msg;
+    RT_ZERO(Msg);
+
+    VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient,
+                       VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_LIST_CLOSE, VBOX_SHARED_CLIPBOARD_CPARMS_LIST_CLOSE);
+
+    Msg.uContext.SetUInt32(0); /** @todo Context ID not used yet. */
+    Msg.uHandle.SetUInt64(hList);
+
+    int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
+
+    LogFlowFuncLeaveRC(rc);
+    return rc;
+}
+
+VBGLR3DECL(int) VbglR3ClipboardListCloseRecv(HGCMCLIENTID idClient, PSHAREDCLIPBOARDLISTHANDLE phList)
+{
+    AssertPtrReturn(phList, VERR_INVALID_POINTER);
+
+    VBoxClipboardListCloseMsg Msg;
+    RT_ZERO(Msg);
+
+    VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient,
+                       VBOX_SHARED_CLIPBOARD_GUEST_FN_MSG_GET, VBOX_SHARED_CLIPBOARD_CPARMS_LIST_CLOSE);
+
+    Msg.uContext.SetUInt32(VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_LIST_CLOSE);
+    Msg.uHandle.SetUInt64(0);
+
+    int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
+    if (RT_SUCCESS(rc))
+    {
+        rc = Msg.uHandle.GetUInt64(phList); AssertRC(rc);
+    }
+
+    LogFlowFuncLeaveRC(rc);
+    return rc;
+}
+
+VBGLR3DECL(int) VbglR3ClipboardListHdrRead(HGCMCLIENTID idClient, SHAREDCLIPBOARDLISTHANDLE hList, uint32_t fFlags,
+                                           PVBOXCLIPBOARDLISTHDR pListHdr)
 {
     AssertPtrReturn(pListHdr, VERR_INVALID_POINTER);
 
-    VBoxClipboardListOpenMsg Msg;
-    RT_ZERO(Msg);
-
-    VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient,
-                       VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_LIST_OPEN, VBOX_SHARED_CLIPBOARD_CPARMS_LIST_OPEN);
-
-    Msg.uContext.SetUInt32(0); /** @todo Context ID not used yet. */
-    Msg.uHandle.SetUInt64(0);
-    Msg.fList.SetUInt32(0);
+    VBoxClipboardListHdrMsg Msg;
+    RT_ZERO(Msg);
+
+    VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient,
+                       VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_HDR_READ, VBOX_SHARED_CLIPBOARD_CPARMS_LIST_HDR);
+
+    Msg.ReqParms.uContext.SetUInt32(0); /** @todo Context ID not used yet. */
+    Msg.ReqParms.uHandle.SetUInt64(hList);
+    Msg.ReqParms.fFlags.SetUInt32(fFlags);
+
     Msg.fFeatures.SetUInt32(0);
-    Msg.cbFilter.SetUInt32(0);
-    Msg.pvFilter.SetPtr(pListHdr->pszFilter, pListHdr->cbFilter);
-
-    int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
-    if (RT_SUCCESS(rc))
-    {
-        rc = Msg.fList.GetUInt32(&pListHdr->fList);         AssertRC(rc);
-        rc = Msg.fFeatures.GetUInt32(&pListHdr->fFeatures); AssertRC(rc);
-    }
-
-    LogFlowFuncLeaveRC(rc);
-    return rc;
-}
-
-static int vbglR3ClipboardRecvListClose(HGCMCLIENTID idClient, PVBOXCLIPBOARDLISTHANDLE phList)
-{
-    AssertPtrReturn(phList, VERR_INVALID_POINTER);
-
-    VBoxClipboardListCloseMsg Msg;
-    RT_ZERO(Msg);
-
-    VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient,
-                       VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_LIST_CLOSE, VBOX_SHARED_CLIPBOARD_CPARMS_LIST_CLOSE);
-
-    Msg.uContext.SetUInt32(0); /** @todo Context ID not used yet. */
-    Msg.uHandle.SetUInt64(0);
-
-    int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
-    if (RT_SUCCESS(rc))
-    {
-        rc = Msg.uHandle.GetUInt64(phList); AssertRC(rc);
-    }
-
-    LogFlowFuncLeaveRC(rc);
-    return rc;
-}
-
-static int vbglR3ClipboardRecvListHdrRead(HGCMCLIENTID idClient, PVBOXCLIPBOARDLISTHANDLE phList, PVBOXCLIPBOARDLISTHDR pListHdr)
-{
-    AssertPtrReturn(pListHdr, VERR_INVALID_POINTER);
-    AssertPtrReturn(phList,   VERR_INVALID_POINTER);
-
-    VBoxClipboardListHdrReadMsg Msg;
-    RT_ZERO(Msg);
-
-    VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient,
-                       VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_LIST_HDR_READ, VBOX_SHARED_CLIPBOARD_CPARMS_LIST_HDR_READ);
-
-    Msg.uContext.SetUInt32(0); /** @todo Context ID not used yet. */
-    Msg.uHandle.SetUInt64(0);
+    Msg.cbTotalSize.SetUInt32(0);
     Msg.cTotalObjects.SetUInt64(0);
     Msg.cbTotalSize.SetUInt64(0);
@@ -261,26 +426,90 @@
     if (RT_SUCCESS(rc))
     {
-        rc = Msg.uHandle.GetUInt64(phList); AssertRC(rc);
-    }
-
-    LogFlowFuncLeaveRC(rc);
-    return rc;
-}
-
-static int vbglR3ClipboardRecvListEntryRead(HGCMCLIENTID idClient, PVBOXCLIPBOARDLISTHANDLE phList,
-                                            PVBOXCLIPBOARDLISTENTRY pListEntry)
+        rc = Msg.fFeatures.GetUInt32(&pListHdr->fFeatures);
+        if (RT_SUCCESS(rc))
+            rc = Msg.cTotalObjects.GetUInt64(&pListHdr->cTotalObjects);
+        if (RT_SUCCESS(rc))
+            rc = Msg.cbTotalSize.GetUInt64(&pListHdr->cbTotalSize);
+        if (RT_SUCCESS(rc))
+            rc = Msg.enmCompression.GetUInt32(&pListHdr->enmCompression);
+        if (RT_SUCCESS(rc))
+            rc = Msg.enmChecksumType.GetUInt32(&pListHdr->enmChecksumType);
+    }
+
+    LogFlowFuncLeaveRC(rc);
+    return rc;
+}
+
+VBGLR3DECL(int) VbglR3ClipboardListHdrReadRecvReq(HGCMCLIENTID idClient, PSHAREDCLIPBOARDLISTHANDLE phList, uint32_t *pfFlags)
+{
+    AssertPtrReturn(phList,  VERR_INVALID_POINTER);
+    AssertPtrReturn(pfFlags, VERR_INVALID_POINTER);
+
+    VBoxClipboardListHdrReadReqMsg Msg;
+    RT_ZERO(Msg);
+
+    VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient,
+                       VBOX_SHARED_CLIPBOARD_GUEST_FN_MSG_GET, VBOX_SHARED_CLIPBOARD_CPARMS_LIST_HDR_READ_REQ);
+
+    Msg.ReqParms.uContext.SetUInt32(VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_LIST_HDR_READ);
+    Msg.ReqParms.uHandle.SetUInt64(0);
+    Msg.ReqParms.fFlags.SetUInt32(0);
+
+    int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
+    if (RT_SUCCESS(rc))
+    {
+        if (RT_SUCCESS(rc))
+            rc = Msg.ReqParms.uHandle.GetUInt64(phList);
+        if (RT_SUCCESS(rc))
+            rc = Msg.ReqParms.fFlags.GetUInt32(pfFlags);
+    }
+
+    LogFlowFuncLeaveRC(rc);
+    return rc;
+}
+
+VBGLR3DECL(int) VbglR3ClipboardListHdrWrite(HGCMCLIENTID idClient, SHAREDCLIPBOARDLISTHANDLE hList,
+                                            PVBOXCLIPBOARDLISTHDR pListHdr)
+{
+    AssertPtrReturn(pListHdr, VERR_INVALID_POINTER);
+
+    VBoxClipboardListHdrMsg Msg;
+    RT_ZERO(Msg);
+
+    VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient,
+                       VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_HDR_WRITE, VBOX_SHARED_CLIPBOARD_CPARMS_LIST_HDR);
+
+    Msg.ReqParms.uContext.SetUInt32(0);
+    Msg.ReqParms.uHandle.SetUInt64(hList);
+    Msg.ReqParms.fFlags.SetUInt32(0);
+
+    Msg.fFeatures.SetUInt32(0);
+    Msg.cbTotalSize.SetUInt32(pListHdr->fFeatures);
+    Msg.cTotalObjects.SetUInt64(pListHdr->cTotalObjects);
+    Msg.cbTotalSize.SetUInt64(pListHdr->cbTotalSize);
+    Msg.enmCompression.SetUInt32(pListHdr->enmCompression);
+    Msg.enmChecksumType.SetUInt32(pListHdr->enmChecksumType);
+
+    int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
+
+    LogFlowFuncLeaveRC(rc);
+    return rc;
+}
+
+VBGLR3DECL(int) VbglR3ClipboardListEntryRead(HGCMCLIENTID idClient, SHAREDCLIPBOARDLISTHANDLE hList,
+                                             PVBOXCLIPBOARDLISTENTRY pListEntry)
 {
     AssertPtrReturn(pListEntry, VERR_INVALID_POINTER);
-    AssertPtrReturn(phList,     VERR_INVALID_POINTER);
-
-    VBoxClipboardListEntryReadMsg Msg;
-    RT_ZERO(Msg);
-
-    VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient,
-                       VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_LIST_ENTRY_READ, VBOX_SHARED_CLIPBOARD_CPARMS_LIST_ENTRY_READ);
-
-    Msg.uContext.SetUInt32(0); /** @todo Context ID not used yet. */
-    Msg.uHandle.SetUInt64(0);
-    Msg.fInfo.SetUInt32(0);
+
+    VBoxClipboardListEntryMsg Msg;
+    RT_ZERO(Msg);
+
+    VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient,
+                       VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_ENTRY_READ, VBOX_SHARED_CLIPBOARD_CPARMS_LIST_ENTRY);
+
+    Msg.ReqParms.uContext.SetUInt32(0); /** @todo Context ID not used yet. */
+    Msg.ReqParms.uHandle.SetUInt64(hList);
+    Msg.ReqParms.fInfo.SetUInt32(0);
+
     Msg.cbInfo.SetUInt32(0);
     Msg.pvInfo.SetPtr(pListEntry->pvInfo, pListEntry->cbInfo);
@@ -289,8 +518,57 @@
     if (RT_SUCCESS(rc))
     {
-        rc = Msg.uHandle.GetUInt64(phList);             AssertRC(rc);
-        rc = Msg.fInfo.GetUInt32(&pListEntry->fInfo);   AssertRC(rc);
         rc = Msg.cbInfo.GetUInt32(&pListEntry->cbInfo); AssertRC(rc);
     }
+
+    LogFlowFuncLeaveRC(rc);
+    return rc;
+}
+
+VBGLR3DECL(int) VbglR3ClipboardListEntryReadRecvReq(HGCMCLIENTID idClient, PSHAREDCLIPBOARDLISTHANDLE phList, uint32_t *pfInfo)
+{
+    AssertPtrReturn(phList, VERR_INVALID_POINTER);
+    AssertPtrReturn(pfInfo, VERR_INVALID_POINTER);
+
+    VBoxClipboardListEntryReadReqMsg Msg;
+    RT_ZERO(Msg);
+
+    VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient,
+                       VBOX_SHARED_CLIPBOARD_GUEST_FN_MSG_GET, VBOX_SHARED_CLIPBOARD_CPARMS_LIST_ENTRY_READ_REQ);
+
+    Msg.ReqParms.uContext.SetUInt32(VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_LIST_ENTRY_READ);
+    Msg.ReqParms.uHandle.SetUInt64(0);
+    Msg.ReqParms.fInfo.SetUInt32(0);
+
+    int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
+    if (RT_SUCCESS(rc))
+    {
+        rc = Msg.ReqParms.uHandle.GetUInt64(phList); AssertRC(rc);
+        if (RT_SUCCESS(rc))
+            rc = Msg.ReqParms.fInfo.GetUInt32(pfInfo); AssertRC(rc);
+    }
+
+    LogFlowFuncLeaveRC(rc);
+    return rc;
+}
+
+VBGLR3DECL(int) VbglR3ClipboardListEntryWrite(HGCMCLIENTID idClient, SHAREDCLIPBOARDLISTHANDLE hList,
+                                              PVBOXCLIPBOARDLISTENTRY pListEntry)
+{
+    AssertPtrReturn(pListEntry, VERR_INVALID_POINTER);
+
+    VBoxClipboardListEntryMsg Msg;
+    RT_ZERO(Msg);
+
+    VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient,
+                       VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_ENTRY_WRITE, VBOX_SHARED_CLIPBOARD_CPARMS_LIST_ENTRY);
+
+    Msg.ReqParms.uContext.SetUInt32(0); /** @todo Context ID not used yet. */
+    Msg.ReqParms.uHandle.SetUInt64(hList);
+    Msg.ReqParms.fInfo.SetUInt32(pListEntry->fInfo);
+
+    Msg.cbInfo.SetUInt32(pListEntry->cbInfo);
+    Msg.pvInfo.SetPtr(pListEntry->pvInfo, pListEntry->cbInfo);
+
+    int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
 
     LogFlowFuncLeaveRC(rc);
@@ -310,23 +588,5 @@
     uint32_t uMsg   = 0;
     uint32_t cParms = 0;
-    int rc = vbglR3ClipboardGetNextMsgType(idClient, &uMsg, &cParms, true /* fWait */);
-    if (RT_SUCCESS(rc))
-    {
-        /** @todo Check for VM session change. */
-    }
-
-#if 0
-    typedef struct _
-    {
-        union
-        {
-            struct Dir
-            {
-                RTDIR hDir;
-            };
-        } u;
-    };
-#endif
-
+    int rc = vbglR3ClipboardMsgPeekWait(idClient, &uMsg, &cParms, NULL /* pidRestoreCheck */);
     if (RT_SUCCESS(rc))
     {
@@ -340,17 +600,21 @@
                 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_LIST_OPEN\n"));
 
-                VBOXCLIPBOARDLISTHDR listHdr;
-                rc = SharedClipboardURIListHdrInit(&listHdr);
+                VBOXCLIPBOARDLISTOPENPARMS openParmsList;
+                rc = SharedClipboardURIListOpenParmsInit(&openParmsList);
                 if (RT_SUCCESS(rc))
                 {
-                    rc = vbglR3ClipboardRecvListOpen(idClient, &listHdr);
+                    rc = VbglR3ClipboardListOpenRecv(idClient, &openParmsList);
                     if (RT_SUCCESS(rc))
                     {
-                        rc = SharedClipboardURITransferListOpen(pTransfer, &listHdr, NULL /* phList */);
+                        SHAREDCLIPBOARDLISTHANDLE hList = SHAREDCLIPBOARDLISTHANDLE_INVALID;
+                        rc = SharedClipboardURITransferListOpen(pTransfer, &openParmsList, &hList);
+
+                        /* Reply in any case. */
+                        int rc2 = VbglR3ClipboardListOpenReply(idClient, rc, hList);
+                        AssertRC(rc2);
                     }
 
-                    SharedClipboardURIListHdrDestroy(&listHdr);
+                    SharedClipboardURIListOpenParmsDestroy(&openParmsList);
                 }
-
                 break;
             }
@@ -360,6 +624,6 @@
                 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_LIST_CLOSE\n"));
 
-                VBOXCLIPBOARDLISTHANDLE hList;
-                rc = vbglR3ClipboardRecvListClose(idClient, &hList);
+                SHAREDCLIPBOARDLISTHANDLE hList;
+                rc = VbglR3ClipboardListCloseRecv(idClient, &hList);
                 if (RT_SUCCESS(rc))
                 {
@@ -376,21 +640,16 @@
                 /** @todo Handle filter + list features. */
 
-                VBOXCLIPBOARDLISTHDR listHdr;
-                rc = SharedClipboardURIListHdrInit(&listHdr);
+                SHAREDCLIPBOARDLISTHANDLE hList  = SHAREDCLIPBOARDLISTHANDLE_INVALID;
+                uint32_t                  fFlags = 0;
+                rc = VbglR3ClipboardListHdrReadRecvReq(idClient, &hList, &fFlags);
                 if (RT_SUCCESS(rc))
                 {
-                    VBOXCLIPBOARDLISTHANDLE hList;
-                    rc = vbglR3ClipboardRecvListHdrRead(idClient, &hList, &listHdr);
+                    VBOXCLIPBOARDLISTHDR hdrList;
+                    rc = SharedClipboardURITransferListGetHeader(pTransfer, hList, &hdrList);
                     if (RT_SUCCESS(rc))
                     {
-                        if (SharedClipboardURITransferListHandleIsValid(pTransfer, hList))
-                        {
-                            rc = VbglR3ClipboardSendListHdrWrite(idClient, hList, &listHdr);
-                        }
-                        else
-                            rc = VERR_INVALID_HANDLE;
+                        rc = VbglR3ClipboardListHdrWrite(idClient, hList, &hdrList);
+                        SharedClipboardURIListHdrDestroy(&hdrList);
                     }
-
-                    SharedClipboardURIListHdrDestroy(&listHdr);
                 }
 
@@ -398,10 +657,18 @@
             }
 
+        #if 0
             case VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_LIST_HDR_WRITE:
             {
                 LogFlowFunc(("VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_LIST_HDR_WRITE\n"));
-                pEvent->enmType = VBGLR3CLIPBOARDEVENTTYPE_URI_LIST_HDR_WRITE;
+
+                VBOXCLIPBOARDLISTHDR hdrList;
+                rc = SharedClipboardURIListHdrInit(&hdrList);
+                if (RT_SUCCESS(rc))
+                {
+                    rc = VBglR3ClipboardListHdrRecv(idClient, )
+                }
                 break;
             }
+        #endif
 
             case VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_LIST_ENTRY_READ:
@@ -413,21 +680,23 @@
                 if (RT_SUCCESS(rc))
                 {
-                    VBOXCLIPBOARDLISTHANDLE hList;
-                    rc = vbglR3ClipboardRecvListEntryRead(idClient, &hList, &listEntry);
+                    SHAREDCLIPBOARDLISTHANDLE hList;
+                    uint32_t                  fInfo;
+                    rc = VbglR3ClipboardListEntryReadRecvReq(idClient, &hList, &fInfo);
                     if (RT_SUCCESS(rc))
                     {
-                        if (SharedClipboardURITransferListHandleIsValid(pTransfer, hList))
+                        rc = SharedClipboardURITransferListRead(pTransfer, hList, &listEntry);
+                        if (RT_SUCCESS(rc))
                         {
-                            rc = VbglR3ClipboardSendListEntryWrite(idClient, hList, &listEntry);
+                            rc = VbglR3ClipboardListEntryWrite(idClient, hList, &listEntry);
                         }
-                        else
-                            rc = VERR_INVALID_HANDLE;
                     }
 
                     SharedClipboardURIListEntryDestroy(&listEntry);
                 }
+
                 break;
             }
 
+        #if 0
             case VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_LIST_ENTRY_WRITE:
             {
@@ -436,4 +705,5 @@
                 break;
             }
+        #endif
 
             case VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_OBJ_OPEN:
@@ -458,4 +728,5 @@
             }
 
+        #if 0
             case VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_OBJ_WRITE:
             {
@@ -464,4 +735,5 @@
                 break;
             }
+        #endif
 #endif /* VBOX_WITH_SHARED_CLIPBOARD_URI_LIST */
 
@@ -471,5 +743,4 @@
         }
     }
-
 
     if (RT_SUCCESS(rc))
@@ -485,5 +756,5 @@
     {
         /* Report error back to the host. */
-        VbglR3ClipboardWriteError(idClient, rc);
+        //VbglR3ClipboardWriteError(idClient, rc);
 
         VbglR3ClipboardEventFree(pEvent);
@@ -514,4 +785,28 @@
     RTMemFree(pEvent);
     pEvent = NULL;
+}
+
+#if 0
+VBGLR3DECL(int) VbglR3ClipboardListHdrReadRecv(HGCMCLIENTID idClient, PVBOXCLIPBOARDLISTHANDLE phList)
+{
+    AssertPtrReturn(phList, VERR_INVALID_POINTER);
+
+    VBoxClipboardListHdrReadMsg Msg;
+    RT_ZERO(Msg);
+
+    VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient,
+                       VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_HDR_READ, VBOX_SHARED_CLIPBOARD_CPARMS_LIST_HDR_READ);
+
+    Msg.uContext.SetUInt32(0); /** @todo Not used yet. */
+    Msg.uHandle.SetUInt64(0);
+
+    int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
+    if (RT_SUCCESS(rc))
+    {
+        Msg.uHandle.GetUInt32(phList);
+    }
+
+    LogFlowFuncLeaveRC(rc);
+    return rc;
 }
 
@@ -524,15 +819,17 @@
  * @param   pListHdr        List header to send.
  */
-VBGLR3DECL(int) VbglR3ClipboardSendListHdrWrite(HGCMCLIENTID idClient,
-                                                VBOXCLIPBOARDLISTHANDLE hList, PVBOXCLIPBOARDLISTHDR pListHdr)
-{
-    VBoxClipboardListHdrWriteMsg Msg;
-    RT_ZERO(Msg);
-
-    VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient,
-                       VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_HDR_WRITE, VBOX_SHARED_CLIPBOARD_CPARMS_LIST_HDR_WRITE);
+VBGLR3DECL(int) VbglR3ClipboardListHdrSend(HGCMCLIENTID idClient,
+                                           VBOXCLIPBOARDLISTHANDLE hList, PVBOXCLIPBOARDLISTHDR pListHdr)
+{
+    AssertPtrReturn(pListHdr, VERR_INVALID_POINTER);
+
+    VBoxClipboardListHdrMsg Msg;
+    RT_ZERO(Msg);
+
+    VBGL_HGCM_HDR_INIT(&Msg.hdr, idClient,
+                       VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_HDR_WRITE, VBOX_SHARED_CLIPBOARD_CPARMS_LIST_HDR);
 
     Msg.uContext.SetUInt32(0); /** @todo Not used yet. */
-    Msg.uHandle.SetUInt64(hList);
+    Msg.fFeatures.SetUInt32(pListHdr->fFeatures);
     Msg.cTotalObjects.SetUInt64(pListHdr->cTotalObjects);
     Msg.cbTotalSize.SetUInt64(pListHdr->cbTotalSize);
@@ -576,4 +873,5 @@
     return rc;
 }
+#endif
 
 VBGLR3DECL(int) VbglR3ClipboardObjOpen(HGCMCLIENTID idClient,
@@ -683,6 +981,6 @@
     Msg.pvData.SetPtr(pvData, cbData);
     Msg.cbData.SetUInt32(cbData);
-    Msg.pvChecksum.SetPtr(NULL, 0);
-    Msg.cbChecksum.SetUInt32(0);
+    Msg.pvChecksum.SetPtr(NULL, 0); /** @todo Implement this. */
+    Msg.cbChecksum.SetUInt32(0); /** @todo Implement this. */
 
     int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
Index: /trunk/src/VBox/GuestHost/SharedClipboard/ClipboardDataObjectImpl-win.cpp
===================================================================
--- /trunk/src/VBox/GuestHost/SharedClipboard/ClipboardDataObjectImpl-win.cpp	(revision 79629)
+++ /trunk/src/VBox/GuestHost/SharedClipboard/ClipboardDataObjectImpl-win.cpp	(revision 79630)
@@ -249,44 +249,50 @@
     if (RT_SUCCESS(rc))
     {
-        VBOXCLIPBOARDLISTHDR Hdr;
-        rc = SharedClipboardURIListHdrInit(&Hdr);
+        VBOXCLIPBOARDLISTOPENPARMS openParmsList;
+        rc = SharedClipboardURIListOpenParmsInit(&openParmsList);
         if (RT_SUCCESS(rc))
         {
-            VBOXCLIPBOARDLISTHANDLE hList;
-            rc = SharedClipboardURITransferListOpen(pTransfer, &Hdr, &hList);
+            SHAREDCLIPBOARDLISTHANDLE hList;
+            rc = SharedClipboardURITransferListOpen(pTransfer, &openParmsList, &hList);
             if (RT_SUCCESS(rc))
             {
-                LogFlowFunc(("hList=%RU64, cTotalObjects=%RU64, cbTotalSize=%RU64\n\n",
-                             hList, Hdr.cTotalObjects, Hdr.cbTotalSize));
-
-                for (uint64_t i = 0; i < Hdr.cTotalObjects; i++)
+                LogFlowFunc(("hList=%RU64\n", hList));
+
+                VBOXCLIPBOARDLISTHDR hdrList;
+                rc = SharedClipboardURITransferListGetHeader(pTransfer, hList, &hdrList);
+                if (RT_SUCCESS(rc))
                 {
-                    VBOXCLIPBOARDLISTENTRY Entry;
-                    rc = SharedClipboardURITransferListRead(pTransfer, hList, &Entry);
+                    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);
                     }
-                    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);
                 }
 
@@ -294,5 +300,5 @@
             }
 
-            SharedClipboardURIListHdrDestroy(&Hdr);
+            SharedClipboardURIListOpenParmsDestroy(&openParmsList);
         }
 
@@ -497,6 +503,7 @@
                     if (RT_SUCCESS(rc))
                     {
+                        /* Don't block for too long here, as this also will screw other apps running on the OS. */
                         LogFunc(("Waiting for listing to arrive ...\n"));
-                        rc = RTSemEventWait(m_EventListComplete, 5 * 60 * 1000 /* 5 min timeout */);
+                        rc = RTSemEventWait(m_EventListComplete, 10 * 1000 /* 10s timeout */);
                         if (RT_SUCCESS(rc))
                         {
@@ -530,6 +537,8 @@
             LogFlowFunc(("FormatIndex_FileContents: m_uObjIdx=%u\n", m_uObjIdx));
 
+            SHAREDCLIPBOARDOBJHANDLE hObj = 0; /** @todo */
+
             /* Hand-in the provider so that our IStream implementation can continue working with it. */
-            hr = VBoxClipboardWinStreamImpl::Create(this /* pParent */, m_pTransfer, m_uObjIdx, &m_pStream);
+            hr = VBoxClipboardWinStreamImpl::Create(this /* pParent */, m_pTransfer, hObj, &m_pStream);
             if (SUCCEEDED(hr))
             {
Index: /trunk/src/VBox/GuestHost/SharedClipboard/ClipboardStreamImpl-win.cpp
===================================================================
--- /trunk/src/VBox/GuestHost/SharedClipboard/ClipboardStreamImpl-win.cpp	(revision 79629)
+++ /trunk/src/VBox/GuestHost/SharedClipboard/ClipboardStreamImpl-win.cpp	(revision 79630)
@@ -47,13 +47,13 @@
 
 VBoxClipboardWinStreamImpl::VBoxClipboardWinStreamImpl(VBoxClipboardWinDataObject *pParent,
-                                                       PSHAREDCLIPBOARDURITRANSFER pTransfer, uint64_t uObjIdx)
+                                                       PSHAREDCLIPBOARDURITRANSFER pTransfer, SHAREDCLIPBOARDOBJHANDLE hObj)
     : m_pParent(pParent)
     , m_lRefCount(1)
     , m_pURITransfer(pTransfer)
-    , m_uObjIdx(uObjIdx)
+    , m_hObj(hObj)
 {
     AssertPtr(m_pURITransfer);
 
-    LogFunc(("m_uObjIdx=%RU64\n", uObjIdx));
+    LogFunc(("m_hObj=%RU64\n", m_hObj));
 }
 
@@ -160,8 +160,6 @@
     LogFlowThisFuncEnter();
 
-    AssertPtr(m_pURITransfer->State.ObjCtx.pObjInfo);
-
-    const uint64_t cbSize      = m_pURITransfer->State.ObjCtx.pObjInfo->cbObject;
-          uint64_t cbProcessed = m_pURITransfer->State.ObjCtx.cbProcessed;
+    const uint64_t cbSize      = m_pURITransfer->ProviderIface.pfnObjGetSize(&m_pURITransfer->ProviderCtx, m_hObj);
+          uint64_t cbProcessed = m_pURITransfer->ProviderIface.pfnObjGetProcessed(&m_pURITransfer->ProviderCtx, m_hObj);
 
     if (cbProcessed == cbSize)
@@ -181,5 +179,5 @@
     if (cbToRead)
     {
-        rc = m_pURITransfer->ProviderIface.pfnObjRead(&m_pURITransfer->ProviderCtx, m_pURITransfer->State.ObjCtx.uHandle,
+        rc = m_pURITransfer->ProviderIface.pfnObjRead(&m_pURITransfer->ProviderCtx, m_hObj,
                                                       pvBuffer, cbToRead, 0 /* fFlags */, &cbRead);
         if (RT_SUCCESS(rc))
@@ -191,5 +189,8 @@
                 m_pParent->OnTransferComplete();
 
-            m_pURITransfer->State.ObjCtx.cbProcessed = cbProcessed;
+    #if 0
+            m_pObj->State.cbProcessed = cbProcessed;
+            Assert(m_pObj->State.cbProcessed <= m_pObj->objInfo.cbObject);
+    #endif
         }
     }
@@ -231,6 +232,4 @@
     if (pStatStg)
     {
-        const SharedClipboardURIObject *pObj = SharedClipboardURITransferGetObject(m_pURITransfer, m_uObjIdx);
-
         RT_BZERO(pStatStg, sizeof(STATSTG));
 
@@ -243,5 +242,6 @@
             case STATFLAG_DEFAULT:
             {
-                int rc2 = RTStrToUtf16(pObj->GetDestPathAbs().c_str(), &pStatStg->pwcsName);
+                int rc2 = RTStrToUtf16(m_pURITransfer->ProviderIface.pfnObjGetPath(&m_pURITransfer->ProviderCtx, m_hObj),
+                                       &pStatStg->pwcsName);
                 if (RT_FAILURE(rc2))
                     hr = E_FAIL;
@@ -259,5 +259,5 @@
             pStatStg->grfMode           = STGM_READ;
             pStatStg->grfLocksSupported = 0;
-            pStatStg->cbSize.QuadPart   = pObj->GetSize();
+            pStatStg->cbSize.QuadPart   = m_pURITransfer->ProviderIface.pfnObjGetSize(&m_pURITransfer->ProviderCtx, m_hObj);
         }
     }
@@ -295,14 +295,14 @@
  * @param   pParent             Pointer to the parent data object.
  * @param   pTransfer           Pointer to URI transfer object to use.
- * @param   uObjIdx             Index of object to handle within the given URI transfer object.
+ * @param   hObj                Handle of URI transfer object.
  * @param   ppStream            Where to return the created stream object on success.
  */
 /* static */
-HRESULT VBoxClipboardWinStreamImpl::Create(VBoxClipboardWinDataObject *pParent,
-                                           PSHAREDCLIPBOARDURITRANSFER pTransfer, uint64_t uObjIdx, IStream **ppStream)
+HRESULT VBoxClipboardWinStreamImpl::Create(VBoxClipboardWinDataObject *pParent, PSHAREDCLIPBOARDURITRANSFER pTransfer,
+                                           SHAREDCLIPBOARDOBJHANDLE hObj, IStream **ppStream)
 {
     AssertPtrReturn(pTransfer, E_POINTER);
 
-    VBoxClipboardWinStreamImpl *pStream = new VBoxClipboardWinStreamImpl(pParent, pTransfer, uObjIdx);
+    VBoxClipboardWinStreamImpl *pStream = new VBoxClipboardWinStreamImpl(pParent, pTransfer, hObj);
     if (pStream)
     {
Index: /trunk/src/VBox/GuestHost/SharedClipboard/clipboard-uri.cpp
===================================================================
--- /trunk/src/VBox/GuestHost/SharedClipboard/clipboard-uri.cpp	(revision 79629)
+++ /trunk/src/VBox/GuestHost/SharedClipboard/clipboard-uri.cpp	(revision 79630)
@@ -19,4 +19,6 @@
 #include <VBox/log.h>
 
+#include <iprt/dir.h>
+#include <iprt/file.h>
 #include <iprt/path.h>
 #include <iprt/semaphore.h>
@@ -90,10 +92,4 @@
     {
         *pListHdrDup = *pListHdr;
-
-        if (pListHdr->pszFilter)
-        {
-            pListHdrDup->pszFilter = RTStrDup(pListHdr->pszFilter);
-            pListHdrDup->cbFilter  = (uint32_t)strlen(pListHdrDup->pszFilter);
-        }
     }
 
@@ -111,4 +107,6 @@
     AssertPtrReturn(pListHdr, VERR_INVALID_POINTER);
 
+    LogFlowFuncEnter();
+
     SharedClipboardURIListHdrReset(pListHdr);
 
@@ -127,13 +125,4 @@
 
     LogFlowFuncEnter();
-
-    if (pListHdr->pszFilter)
-    {
-        Assert(pListHdr->cbFilter);
-
-        RTStrFree(pListHdr->pszFilter);
-        pListHdr->pszFilter = NULL;
-        pListHdr->cbFilter = 0;
-    }
 }
 
@@ -165,8 +154,94 @@
 }
 
-/**
- * Creates (allocates) and initializes a VBOXCLIPBOARDListEntry structure.
- *
- * @param   ppDirData           Where to return the created VBOXCLIPBOARDListEntry structure on success.
+int SharedClipboardURIListOpenParmsCopy(PVBOXCLIPBOARDLISTOPENPARMS pDst, PVBOXCLIPBOARDLISTOPENPARMS pSrc)
+{
+    AssertPtrReturn(pDst, VERR_INVALID_POINTER);
+    AssertPtrReturn(pSrc, VERR_INVALID_POINTER);
+
+    int rc = VINF_SUCCESS;
+
+    if (pSrc->pszFilter)
+    {
+        pDst->pszFilter = RTStrDup(pSrc->pszFilter);
+        if (!pDst->pszFilter)
+            rc = VERR_NO_MEMORY;
+    }
+
+    if (   RT_SUCCESS(rc)
+        && pSrc->pszPath)
+    {
+        pDst->pszPath = RTStrDup(pSrc->pszPath);
+        if (!pDst->pszPath)
+            rc = VERR_NO_MEMORY;
+    }
+
+    if (RT_SUCCESS(rc))
+    {
+        pDst->fList    = pDst->fList;
+        pDst->cbFilter = pSrc->cbFilter;
+        pDst->cbPath   = pSrc->cbPath;
+    }
+
+    return rc;
+}
+
+PVBOXCLIPBOARDLISTOPENPARMS SharedClipboardURIListOpenParmsDup(PVBOXCLIPBOARDLISTOPENPARMS pParms)
+{
+    AssertPtrReturn(pParms, NULL);
+
+    PVBOXCLIPBOARDLISTOPENPARMS pParmsDup = (PVBOXCLIPBOARDLISTOPENPARMS)RTMemAllocZ(sizeof(VBOXCLIPBOARDLISTOPENPARMS));
+    if (!pParmsDup)
+        return NULL;
+
+    int rc = SharedClipboardURIListOpenParmsCopy(pParmsDup, pParms);
+    if (RT_FAILURE(rc))
+    {
+        SharedClipboardURIListOpenParmsDestroy(pParmsDup);
+
+        RTMemFree(pParmsDup);
+        pParmsDup = NULL;
+    }
+
+    return pParmsDup;
+}
+
+int SharedClipboardURIListOpenParmsInit(PVBOXCLIPBOARDLISTOPENPARMS pParms)
+{
+    AssertPtrReturn(pParms, VERR_INVALID_POINTER);
+
+    RT_BZERO(pParms, sizeof(VBOXCLIPBOARDLISTOPENPARMS));
+
+    pParms->cbFilter  = 64;
+    pParms->pszFilter = RTStrAlloc(pParms->cbFilter);
+
+    pParms->cbPath    = RTPATH_MAX;
+    pParms->pszPath   = RTStrAlloc(pParms->cbPath);
+
+    LogFlowFuncLeave();
+    return VINF_SUCCESS;
+}
+
+void SharedClipboardURIListOpenParmsDestroy(PVBOXCLIPBOARDLISTOPENPARMS pParms)
+{
+    if (!pParms)
+        return;
+
+    if (pParms->pszFilter)
+    {
+        RTStrFree(pParms->pszFilter);
+        pParms->pszFilter = NULL;
+    }
+
+    if (pParms->pszPath)
+    {
+        RTStrFree(pParms->pszPath);
+        pParms->pszPath = NULL;
+    }
+}
+
+/**
+ * Creates (allocates) and initializes a clipboard list entry structure.
+ *
+ * @param   ppDirData           Where to return the created clipboard list entry structure on success.
  */
 int SharedClipboardURIListEntryAlloc(PVBOXCLIPBOARDLISTENTRY *ppListEntry)
@@ -184,7 +259,7 @@
 
 /**
- * Frees a VBOXCLIPBOARDListEntry structure.
- *
- * @param   pListEntry         VBOXCLIPBOARDListEntry structure to free.
+ * Frees a clipboard list entry structure.
+ *
+ * @param   pListEntry         Clipboard list entry structure to free.
  */
 void SharedClipboardURIListEntryFree(PVBOXCLIPBOARDLISTENTRY pListEntry)
@@ -198,8 +273,47 @@
 
 /**
- * Duplicates (allocates) a VBOXCLIPBOARDListEntry structure.
- *
- * @returns Duplicated VBOXCLIPBOARDListEntry structure on success.
- * @param   pListEntry          VBOXCLIPBOARDListEntry to duplicate.
+ * (Deep) Copies a clipboard list entry structure.
+ *
+ * @returns VBox status code.
+ * @param   pListEntry          Clipboard list entry to copy.
+ */
+int SharedClipboardURIListEntryCopy(PVBOXCLIPBOARDLISTENTRY pDst, PVBOXCLIPBOARDLISTENTRY pSrc)
+{
+    AssertPtrReturn(pDst, VERR_INVALID_POINTER);
+    AssertPtrReturn(pSrc, VERR_INVALID_POINTER);
+
+    int rc = VINF_SUCCESS;
+
+    *pDst = *pSrc;
+
+    if (pSrc->pvInfo)
+    {
+        pDst->pvInfo = RTMemDup(pSrc->pvInfo, pSrc->cbInfo);
+        if (pDst->pvInfo)
+        {
+            pDst->cbInfo = pSrc->cbInfo;
+        }
+        else
+            rc = VERR_NO_MEMORY;
+    }
+
+    if (RT_FAILURE(rc))
+    {
+        if (pDst->pvInfo)
+        {
+            RTMemFree(pDst->pvInfo);
+            pDst->pvInfo = NULL;
+            pDst->cbInfo = 0;
+        }
+    }
+
+    return rc;
+}
+
+/**
+ * Duplicates (allocates) a clipboard list entry structure.
+ *
+ * @returns Duplicated clipboard list entry structure on success.
+ * @param   pListEntry          Clipboard list entry to duplicate.
  */
 PVBOXCLIPBOARDLISTENTRY SharedClipboardURIListEntryDup(PVBOXCLIPBOARDLISTENTRY pListEntry)
@@ -207,14 +321,16 @@
     AssertPtrReturn(pListEntry, NULL);
 
-    PVBOXCLIPBOARDLISTENTRY pListEntryDup = (PVBOXCLIPBOARDLISTENTRY)RTMemAlloc(sizeof(VBOXCLIPBOARDLISTENTRY));
+    int rc = VINF_SUCCESS;
+
+    PVBOXCLIPBOARDLISTENTRY pListEntryDup = (PVBOXCLIPBOARDLISTENTRY)RTMemAllocZ(sizeof(VBOXCLIPBOARDLISTENTRY));
     if (pListEntryDup)
-    {
-        *pListEntryDup = *pListEntry;
-
-        if (pListEntry->pvInfo)
-        {
-            pListEntryDup->pvInfo= RTMemDup(pListEntry->pvInfo, pListEntry->cbInfo);
-            pListEntryDup->cbInfo = pListEntry->cbInfo;
-        }
+        rc = SharedClipboardURIListEntryCopy(pListEntryDup, pListEntry);
+
+    if (RT_FAILURE(rc))
+    {
+        SharedClipboardURIListEntryDestroy(pListEntryDup);
+
+        RTMemFree(pListEntryDup);
+        pListEntryDup = NULL;
     }
 
@@ -223,7 +339,7 @@
 
 /**
- * Initializes a VBOXCLIPBOARDListEntry structure.
- *
- * @param   pListEntry          VBOXCLIPBOARDListEntry structure to initialize.
+ * Initializes a clipboard list entry structure.
+ *
+ * @param   pListEntry          clipboard list entry structure to initialize.
  */
 int SharedClipboardURIListEntryInit(PVBOXCLIPBOARDLISTENTRY pListEntry)
@@ -235,10 +351,13 @@
 
 /**
- * Initializes a VBOXCLIPBOARDListEntry structure.
- *
- * @param   pListEntry          VBOXCLIPBOARDListEntry structure to destroy.
+ * Initializes a clipboard list entry structure.
+ *
+ * @param   pListEntry          clipboard list entry structure to destroy.
  */
 void SharedClipboardURIListEntryDestroy(PVBOXCLIPBOARDLISTENTRY pListEntry)
 {
+    if (!pListEntry)
+        return;
+
     if (pListEntry->pvInfo)
     {
@@ -543,5 +662,4 @@
 
     pObjCtx->uHandle  = SHAREDCLIPBOARDOBJHANDLE_INVALID;
-    pObjCtx->pObjInfo = NULL;
 
     return VINF_SUCCESS;
@@ -558,6 +676,4 @@
 
     LogFlowFuncEnter();
-
-    pObjCtx->pObjInfo = NULL;
 }
 
@@ -571,6 +687,5 @@
 {
     return (   pObjCtx
-            && pObjCtx->uHandle != SHAREDCLIPBOARDOBJHANDLE_INVALID
-            && pObjCtx->pObjInfo);
+            && pObjCtx->uHandle != SHAREDCLIPBOARDOBJHANDLE_INVALID);
 }
 
@@ -615,18 +730,12 @@
     RT_ZERO(pTransfer->Callbacks);
 
-    pTransfer->pURIList = new SharedClipboardURIList();
-    if (pTransfer->pURIList)
-    {
-        pTransfer->Events.pMap = new SharedClipboardURITransferEventMap();
-        if (pTransfer->Events.pMap)
-        {
-            rc = SharedClipboardURIObjCtxInit(&pTransfer->State.ObjCtx);
-            if (RT_SUCCESS(rc))
-            {
-                *ppTransfer = pTransfer;
-            }
-        }
-        else
-            rc = VERR_NO_MEMORY;
+    pTransfer->pMapEvents = new SharedClipboardURITransferEventMap();
+    if (pTransfer->pMapEvents)
+    {
+        pTransfer->pMapLists = new SharedClipboardURIListMap();
+        if (pTransfer->pMapLists)
+        {
+            *ppTransfer = pTransfer;
+        }
     }
     else
@@ -659,17 +768,15 @@
         return rc;
 
-    if (pTransfer->pURIList)
-    {
-        delete pTransfer->pURIList;
-        pTransfer->pURIList = NULL;
-    }
-
-    if (pTransfer->Events.pMap)
-    {
-        delete pTransfer->Events.pMap;
-        pTransfer->Events.pMap = NULL;
-    }
-
-    SharedClipboardURIObjCtxDestroy(&pTransfer->State.ObjCtx);
+    if (pTransfer->pMapEvents)
+    {
+        delete pTransfer->pMapEvents;
+        pTransfer->pMapEvents = NULL;
+    }
+
+    if (pTransfer->pMapLists)
+    {
+        delete pTransfer->pMapLists;
+        pTransfer->pMapLists = NULL;
+    }
 
     LogFlowFuncLeave();
@@ -699,33 +806,259 @@
 }
 
-int SharedClipboardURITransferListOpen(PSHAREDCLIPBOARDURITRANSFER pTransfer, PVBOXCLIPBOARDLISTHDR pListHdr,
-                                       PVBOXCLIPBOARDLISTHANDLE phList)
+static SHAREDCLIPBOARDLISTHANDLE sharedClipboardURITransferListHandleNew(PSHAREDCLIPBOARDURITRANSFER pTransfer)
+{
+    RT_NOREF(pTransfer);
+
+    return 42; /** @todo FIX !!!!! */
+}
+
+int SharedClipboardURITransferListOpen(PSHAREDCLIPBOARDURITRANSFER pTransfer, PVBOXCLIPBOARDLISTOPENPARMS pOpenParms,
+                                       PSHAREDCLIPBOARDLISTHANDLE phList)
+{
+    AssertPtrReturn(pTransfer,  VERR_INVALID_POINTER);
+    AssertPtrReturn(pOpenParms, VERR_INVALID_POINTER);
+    AssertPtrReturn(phList,     VERR_INVALID_POINTER);
+
+    int rc;
+
+    SHAREDCLIPBOARDLISTHANDLE hList = SHAREDCLIPBOARDLISTHANDLE_INVALID;
+
+    if (pTransfer->State.enmSource == SHAREDCLIPBOARDSOURCE_LOCAL)
+    {
+        PSHAREDCLIPBOARDURILISTHANDLEINFO pInfo
+            = (PSHAREDCLIPBOARDURILISTHANDLEINFO)RTMemAlloc(sizeof(SHAREDCLIPBOARDURILISTHANDLEINFO));
+        if (pInfo)
+        {
+            if (   !pOpenParms->pszPath
+                || !strlen(pOpenParms->pszPath))
+                RTStrAPrintf(&pOpenParms->pszPath, "C:\\Temp"); /** @todo FIX !!!! */
+
+            RTFSOBJINFO objInfo;
+            rc = RTPathQueryInfo(pOpenParms->pszPath, &objInfo, RTFSOBJATTRADD_NOTHING);
+            if (RTFS_IS_DIRECTORY(objInfo.Attr.fMode))
+            {
+                rc = RTDirOpen(&pInfo->u.Local.hDirRoot, pOpenParms->pszPath);
+            }
+            else if (RTFS_IS_FILE(objInfo.Attr.fMode))
+            {
+                rc = RTFileOpen(&pInfo->u.Local.hFile, pOpenParms->pszPath, RTFILE_O_READ | RTFILE_O_DENY_WRITE);
+            }
+            else if (RTFS_IS_SYMLINK(objInfo.Attr.fMode))
+            {
+                rc = VERR_NOT_IMPLEMENTED; /** @todo */
+            }
+            else
+                AssertFailedStmt(rc = VERR_NOT_SUPPORTED);
+
+            if (RT_SUCCESS(rc))
+                rc = SharedClipboardURIListOpenParmsCopy(&pInfo->OpenParms, pOpenParms);
+
+            if (RT_SUCCESS(rc))
+            {
+                pInfo->fMode = objInfo.Attr.fMode;
+
+                hList = sharedClipboardURITransferListHandleNew(pTransfer);
+
+                pTransfer->pMapLists->insert(
+                    std::pair<SHAREDCLIPBOARDLISTHANDLE, PSHAREDCLIPBOARDURILISTHANDLEINFO>(hList, pInfo));
+            }
+            else
+            {
+                if (RTFS_IS_DIRECTORY(objInfo.Attr.fMode))
+                {
+                    if (RTDirIsValid(pInfo->u.Local.hDirRoot))
+                        RTDirClose(pInfo->u.Local.hDirRoot);
+                }
+                else if (RTFS_IS_FILE(objInfo.Attr.fMode))
+                {
+                    if (RTFileIsValid(pInfo->u.Local.hFile))
+                        RTFileClose(pInfo->u.Local.hFile);
+                }
+
+                RTMemFree(pInfo);
+                pInfo = NULL;
+            }
+        }
+        else
+            rc = VERR_NO_MEMORY;
+    }
+    else if (pTransfer->State.enmSource == SHAREDCLIPBOARDSOURCE_REMOTE)
+    {
+        if (pTransfer->ProviderIface.pfnListOpen)
+        {
+            rc = pTransfer->ProviderIface.pfnListOpen(&pTransfer->ProviderCtx, pOpenParms, &hList);
+        }
+        else
+            rc = VERR_NOT_SUPPORTED;
+    }
+    else
+        AssertFailedStmt(rc = VERR_NOT_IMPLEMENTED);
+
+    if (RT_SUCCESS(rc))
+        *phList = hList;
+
+    LogFlowFuncLeaveRC(rc);
+    return rc;
+}
+
+int SharedClipboardURITransferListClose(PSHAREDCLIPBOARDURITRANSFER pTransfer, SHAREDCLIPBOARDLISTHANDLE hList)
 {
     AssertPtrReturn(pTransfer, VERR_INVALID_POINTER);
-    AssertPtrReturn(pListHdr,  VERR_INVALID_POINTER);
-    /* phList is optional. */
+
+    if (hList == SHAREDCLIPBOARDLISTHANDLE_INVALID)
+        return VINF_SUCCESS;
 
     int rc = VINF_SUCCESS;
 
-    VBOXCLIPBOARDLISTHANDLE hList = SHAREDCLIPBOARDLISTHANDLE_INVALID;
-
-    if (pTransfer->ProviderIface.pfnListOpen)
-        rc = pTransfer->ProviderIface.pfnListOpen(&pTransfer->ProviderCtx, pListHdr, &hList);
-
+    if (pTransfer->State.enmSource == SHAREDCLIPBOARDSOURCE_LOCAL)
+    {
+        SharedClipboardURIListMap::iterator itList = pTransfer->pMapLists->find(hList);
+        if (itList != pTransfer->pMapLists->end())
+        {
+            PSHAREDCLIPBOARDURILISTHANDLEINFO pInfo = itList->second;
+            AssertPtr(pInfo);
+
+            if (RTDirIsValid(pInfo->u.Local.hDirRoot))
+                RTDirClose(pInfo->u.Local.hDirRoot);
+
+            RTMemFree(pInfo);
+
+            pTransfer->pMapLists->erase(itList);
+        }
+        else
+            rc = VERR_NOT_FOUND;
+    }
+    else if (pTransfer->State.enmSource == SHAREDCLIPBOARDSOURCE_REMOTE)
+    {
+        if (pTransfer->ProviderIface.pfnListClose)
+        {
+            rc = pTransfer->ProviderIface.pfnListClose(&pTransfer->ProviderCtx, hList);
+        }
+        else
+            rc = VERR_NOT_SUPPORTED;
+    }
+
+    LogFlowFuncLeaveRC(rc);
+    return rc;
+}
+
+static int sharedClipboardURITransferListHdrAddFile(PVBOXCLIPBOARDLISTHDR pHdr, const char *pszPath)
+{
+    uint64_t cbSize = 0;
+    int rc = RTFileQuerySize(pszPath, &cbSize);
     if (RT_SUCCESS(rc))
     {
-        AssertPtr(pTransfer->ProviderIface.pfnListHdrRead);
-        rc = pTransfer->ProviderIface.pfnListHdrRead(&pTransfer->ProviderCtx, hList, pListHdr);
-    }
-
+        pHdr->cbTotalSize  += cbSize;
+        pHdr->cTotalObjects++;
+    }
+
+    LogFlowFuncLeaveRC(rc);
+    return rc;
+}
+
+static int sharedClipboardURITransferListHdrFromDir(PVBOXCLIPBOARDLISTHDR pHdr,
+                                                    const char *pcszSrcPath, const char *pcszDstPath,
+                                                    const char *pcszDstBase, size_t cchDstBase)
+{
+    AssertPtrReturn(pcszSrcPath, VERR_INVALID_POINTER);
+    AssertPtrReturn(pcszDstBase, VERR_INVALID_POINTER);
+    AssertPtrReturn(pcszDstPath, VERR_INVALID_POINTER);
+
+    LogFlowFunc(("pcszSrcPath=%s, pcszDstPath=%s, pcszDstBase=%s, cchDstBase=%zu\n",
+                 pcszSrcPath, pcszDstPath, pcszDstBase, cchDstBase));
+
+    RTFSOBJINFO objInfo;
+    int rc = RTPathQueryInfo(pcszSrcPath, &objInfo, RTFSOBJATTRADD_NOTHING);
     if (RT_SUCCESS(rc))
     {
-        if (phList)
-            *phList = hList;
-    }
-    else if (pTransfer->ProviderIface.pfnListClose)
-    {
-        int rc2 = pTransfer->ProviderIface.pfnListClose(&pTransfer->ProviderCtx, hList);
-        AssertRC(rc2);
+        if (RTFS_IS_DIRECTORY(objInfo.Attr.fMode))
+        {
+            pHdr->cTotalObjects++; /* Add directory itself. */
+
+            if (RT_SUCCESS(rc))
+            {
+                RTDIR hDir;
+                rc = RTDirOpen(&hDir, pcszSrcPath);
+                if (RT_SUCCESS(rc))
+                {
+                    size_t        cbDirEntry = 0;
+                    PRTDIRENTRYEX pDirEntry  = NULL;
+                    do
+                    {
+                        /* Retrieve the next directory entry. */
+                        rc = RTDirReadExA(hDir, &pDirEntry, &cbDirEntry, RTFSOBJATTRADD_NOTHING, RTPATH_F_ON_LINK);
+                        if (RT_FAILURE(rc))
+                        {
+                            if (rc == VERR_NO_MORE_FILES)
+                                rc = VINF_SUCCESS;
+                            break;
+                        }
+
+                        switch (pDirEntry->Info.Attr.fMode & RTFS_TYPE_MASK)
+                        {
+                            case RTFS_TYPE_DIRECTORY:
+                            {
+                                /* Skip "." and ".." entries. */
+                                if (RTDirEntryExIsStdDotLink(pDirEntry))
+                                    break;
+
+                                char *pszSrc = RTPathJoinA(pcszSrcPath, pDirEntry->szName);
+                                if (pszSrc)
+                                {
+                                    char *pszDst = RTPathJoinA(pcszDstPath, pDirEntry->szName);
+                                    if (pszDst)
+                                    {
+                                        rc = sharedClipboardURITransferListHdrFromDir(pHdr, pszSrc, pszDst,
+                                                                                      pcszDstBase, cchDstBase);
+                                        RTStrFree(pszDst);
+                                    }
+                                    else
+                                        rc = VERR_NO_MEMORY;
+
+                                    RTStrFree(pszSrc);
+                                }
+                                else
+                                    rc = VERR_NO_MEMORY;
+                                break;
+                            }
+
+                            case RTFS_TYPE_FILE:
+                            {
+                                char *pszSrc = RTPathJoinA(pcszSrcPath, pDirEntry->szName);
+                                if (pszSrc)
+                                {
+                                    rc = sharedClipboardURITransferListHdrAddFile(pHdr, pszSrc);
+                                    RTStrFree(pszSrc);
+                                }
+                                else
+                                    rc = VERR_NO_MEMORY;
+                                break;
+                            }
+                            case RTFS_TYPE_SYMLINK:
+                            {
+                                /** @todo Not implemented yet. */
+                            }
+
+                            default:
+                                break;
+                        }
+
+                    } while (RT_SUCCESS(rc));
+
+                    RTDirReadExAFree(&pDirEntry, &cbDirEntry);
+                    RTDirClose(hDir);
+                }
+            }
+        }
+        else if (RTFS_IS_FILE(objInfo.Attr.fMode))
+        {
+            rc = sharedClipboardURITransferListHdrAddFile(pHdr, pcszSrcPath);
+        }
+        else if (RTFS_IS_SYMLINK(objInfo.Attr.fMode))
+        {
+            /** @todo Not implemented yet. */
+        }
+        else
+            rc = VERR_NOT_SUPPORTED;
     }
 
@@ -734,12 +1067,210 @@
 }
 
-int SharedClipboardURITransferListClose(PSHAREDCLIPBOARDURITRANSFER pTransfer, VBOXCLIPBOARDLISTHANDLE hList)
+int SharedClipboardURITransferListGetHeader(PSHAREDCLIPBOARDURITRANSFER pTransfer, SHAREDCLIPBOARDLISTHANDLE hList,
+                                            PVBOXCLIPBOARDLISTHDR pHdr)
 {
     AssertPtrReturn(pTransfer, VERR_INVALID_POINTER);
+    AssertPtrReturn(pHdr,      VERR_INVALID_POINTER);
+
+    int rc;
+
+    LogFlowFunc(("hList=%RU64\n", hList));
+
+    if (pTransfer->State.enmSource == SHAREDCLIPBOARDSOURCE_LOCAL)
+    {
+        SharedClipboardURIListMap::iterator itList = pTransfer->pMapLists->find(hList);
+        if (itList != pTransfer->pMapLists->end())
+        {
+            rc = SharedClipboardURIListHdrInit(pHdr);
+            if (RT_SUCCESS(rc))
+            {
+                PSHAREDCLIPBOARDURILISTHANDLEINFO pInfo = itList->second;
+                AssertPtr(pInfo);
+
+                if (RTFS_IS_DIRECTORY(pInfo->fMode))
+                {
+                    char *pszSrcPath = RTStrDup(pInfo->OpenParms.pszPath);
+                    if (pszSrcPath)
+                    {
+                        size_t cbSrcPathLen = RTPathStripTrailingSlash(pszSrcPath);
+                        if (cbSrcPathLen)
+                        {
+                            char *pszFileName = RTPathFilename(pszSrcPath);
+                            if (pszFileName)
+                            {
+                                Assert(pszFileName >= pszSrcPath);
+                                size_t cchDstBase = pszFileName - pszSrcPath;
+                                char *pszDstPath  = &pszSrcPath[cchDstBase];
+
+                                LogFlowFunc(("pszSrcPath=%s, pszFileName=%s, pszDstPath=%s\n", pszSrcPath, pszFileName, pszDstPath));
+                                rc = sharedClipboardURITransferListHdrFromDir(pHdr,
+                                                                              pszSrcPath, pszSrcPath, pszSrcPath, cchDstBase);
+                            }
+                            else
+                                rc = VERR_PATH_NOT_FOUND;
+                        }
+                        else
+                            rc = VERR_INVALID_PARAMETER;
+
+                        RTStrFree(pszSrcPath);
+                    }
+                    else
+                        rc = VERR_NO_MEMORY;
+                }
+                else if (RTFS_IS_FILE(pInfo->fMode))
+                {
+                    pHdr->cTotalObjects = 1;
+
+                    RTFSOBJINFO objInfo;
+                    rc = RTFileQueryInfo(pInfo->u.Local.hFile, &objInfo, RTFSOBJATTRADD_NOTHING);
+                    if (RT_SUCCESS(rc))
+                    {
+                        pHdr->cbTotalSize = objInfo.cbObject;
+                    }
+                }
+                else if (RTFS_IS_SYMLINK(pInfo->fMode))
+                {
+                    rc = VERR_NOT_IMPLEMENTED; /** @todo */
+                }
+                else
+                    AssertFailedStmt(rc = VERR_NOT_SUPPORTED);
+            }
+        }
+        else
+            rc = VERR_NOT_FOUND;
+    }
+    else if (pTransfer->State.enmSource == SHAREDCLIPBOARDSOURCE_REMOTE)
+    {
+        if (pTransfer->ProviderIface.pfnListHdrRead)
+        {
+            rc = pTransfer->ProviderIface.pfnListHdrRead(&pTransfer->ProviderCtx, hList, pHdr);
+        }
+        else
+            rc = VERR_NOT_SUPPORTED;
+    }
+    else
+        AssertFailedStmt(rc = VERR_NOT_IMPLEMENTED);
+
+    LogFlowFuncLeaveRC(rc);
+    return rc;
+}
+
+/**
+ * Returns the current URI object for a clipboard URI transfer list.
+ *
+ * @returns Pointer to URI object.
+ * @param   pTransfer           URI clipboard transfer to return URI object for.
+ */
+PSHAREDCLIPBOARDURITRANSFEROBJ SharedClipboardURITransferListGetObj(PSHAREDCLIPBOARDURITRANSFER pTransfer,
+                                                                    SHAREDCLIPBOARDLISTHANDLE hList, uint64_t uIdx)
+{
+    AssertPtrReturn(pTransfer, NULL);
+
+    RT_NOREF(hList, uIdx);
+
+    LogFlowFunc(("hList=%RU64\n", hList));
+
+    return NULL;
+}
+
+int SharedClipboardURITransferListRead(PSHAREDCLIPBOARDURITRANSFER pTransfer, SHAREDCLIPBOARDLISTHANDLE hList,
+                                       PVBOXCLIPBOARDLISTENTRY pEntry)
+{
+    AssertPtrReturn(pTransfer, VERR_INVALID_POINTER);
+    AssertPtrReturn(pEntry,    VERR_INVALID_POINTER);
 
     int rc = VINF_SUCCESS;
 
-    if (pTransfer->ProviderIface.pfnListClose)
-        rc = pTransfer->ProviderIface.pfnListClose(&pTransfer->ProviderCtx, hList);
+    LogFlowFunc(("hList=%RU64\n", hList));
+
+    if (pTransfer->State.enmSource == SHAREDCLIPBOARDSOURCE_LOCAL)
+    {
+        SharedClipboardURIListMap::iterator itList = pTransfer->pMapLists->find(hList);
+        if (itList != pTransfer->pMapLists->end())
+        {
+            PSHAREDCLIPBOARDURILISTHANDLEINFO pInfo = itList->second;
+            AssertPtr(pInfo);
+
+            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))
+                {
+                    switch (pDirEntry->Info.Attr.fMode & RTFS_TYPE_MASK)
+                    {
+                        case RTFS_TYPE_DIRECTORY:
+                        {
+                            /* Skip "." and ".." entries. */
+                            if (RTDirEntryExIsStdDotLink(pDirEntry))
+                                break;
+
+                            RT_FALL_THROUGH();
+                        }
+
+                        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);
+                }
+            }
+            else if (RTFS_IS_FILE(pInfo->fMode))
+            {
+                RTFSOBJINFO objInfo;
+                rc = RTFileQueryInfo(pInfo->u.Local.hFile, &objInfo, RTFSOBJATTRADD_NOTHING);
+                if (RT_SUCCESS(rc))
+                {
+                    pEntry->pvInfo = (PSHAREDCLIPBOARDFSOBJINFO)RTMemAlloc(sizeof(SHAREDCLIPBOARDFSOBJINFO));
+                    if (pEntry->pvInfo)
+                    {
+                        SharedClipboardFsObjFromIPRT(PSHAREDCLIPBOARDFSOBJINFO(pEntry->pvInfo), &objInfo);
+
+                        pEntry->cbInfo = sizeof(SHAREDCLIPBOARDFSOBJINFO);
+                        pEntry->fInfo  = 0; /** @todo Implement. */
+                    }
+                    else
+                        rc = VERR_NO_MEMORY;
+                }
+            }
+            else if (RTFS_IS_SYMLINK(pInfo->fMode))
+            {
+                rc = VERR_NOT_IMPLEMENTED;
+            }
+            else
+                AssertFailedStmt(rc = VERR_NOT_SUPPORTED);
+        }
+        else
+            rc = VERR_NOT_FOUND;
+    }
+    else if (pTransfer->State.enmSource == SHAREDCLIPBOARDSOURCE_REMOTE)
+    {
+        if (pTransfer->ProviderIface.pfnListEntryRead)
+            rc = pTransfer->ProviderIface.pfnListEntryRead(&pTransfer->ProviderCtx, hList, pEntry);
+        else
+            rc = VERR_NOT_SUPPORTED;
+    }
 
     LogFlowFuncLeaveRC(rc);
@@ -747,25 +1278,15 @@
 }
 
-int SharedClipboardURITransferListRead(PSHAREDCLIPBOARDURITRANSFER pTransfer, VBOXCLIPBOARDLISTHANDLE hList,
-                                       PVBOXCLIPBOARDLISTENTRY pEntry)
-{
-    AssertPtrReturn(pTransfer, VERR_INVALID_POINTER);
+int SharedClipboardURITransferListWrite(PSHAREDCLIPBOARDURITRANSFER pTransfer, SHAREDCLIPBOARDLISTHANDLE hList,
+                                        PVBOXCLIPBOARDLISTENTRY pEntry)
+{
+    RT_NOREF(pTransfer, hList, pEntry);
 
     int rc = VINF_SUCCESS;
 
-    if (pTransfer->ProviderIface.pfnListEntryRead)
-        rc = pTransfer->ProviderIface.pfnListEntryRead(&pTransfer->ProviderCtx, hList, pEntry);
-
-    LogFlowFuncLeaveRC(rc);
-    return rc;
-}
-
-int SharedClipboardURITransferListWrite(PSHAREDCLIPBOARDURITRANSFER pTransfer, VBOXCLIPBOARDLISTHANDLE hList,
-                                        PVBOXCLIPBOARDLISTENTRY pEntry)
-{
-    int rc = VINF_SUCCESS;
-
+#if 0
     if (pTransfer->ProviderIface.pfnListEntryWrite)
         rc = pTransfer->ProviderIface.pfnListEntryWrite(&pTransfer->ProviderCtx, hList, pEntry);
+#endif
 
     LogFlowFuncLeaveRC(rc);
@@ -773,9 +1294,19 @@
 }
 
-bool SharedClipboardURITransferListHandleIsValid(PSHAREDCLIPBOARDURITRANSFER pTransfer, VBOXCLIPBOARDLISTHANDLE hList)
-{
-    RT_NOREF(pTransfer, hList);
-
-    return true; /** @todo Implement this. */
+bool SharedClipboardURITransferListHandleIsValid(PSHAREDCLIPBOARDURITRANSFER pTransfer, SHAREDCLIPBOARDLISTHANDLE hList)
+{
+    bool fIsValid = false;
+
+    if (pTransfer->State.enmSource == SHAREDCLIPBOARDSOURCE_LOCAL)
+    {
+        SharedClipboardURIListMap::iterator itList = pTransfer->pMapLists->find(hList);
+        fIsValid = itList != pTransfer->pMapLists->end();
+    }
+    else if (pTransfer->State.enmSource == SHAREDCLIPBOARDSOURCE_REMOTE)
+    {
+        AssertFailed(); /** @todo Implement. */
+    }
+
+    return fIsValid;
 }
 
@@ -817,5 +1348,5 @@
 
 /**
- * Creates an URI provider for a given transfer.
+ * Sets the URI provider interface for a given transfer.
  *
  * @returns VBox status code.
@@ -823,6 +1354,6 @@
  * @param   pCreationCtx        Provider creation context to use for provider creation.
  */
-int SharedClipboardURITransferProviderCreate(PSHAREDCLIPBOARDURITRANSFER pTransfer,
-                                             PSHAREDCLIPBOARDPROVIDERCREATIONCTX pCreationCtx)
+int SharedClipboardURITransferSetInterface(PSHAREDCLIPBOARDURITRANSFER pTransfer,
+                                           PSHAREDCLIPBOARDPROVIDERCREATIONCTX pCreationCtx)
 {
     AssertPtrReturn(pTransfer,    VERR_INVALID_POINTER);
@@ -854,9 +1385,4 @@
 
     /** @todo Anything else to do here? */
-
-    if (pTransfer->pURIList)
-        pTransfer->pURIList->Clear();
-
-    SharedClipboardURIObjCtxDestroy(&pTransfer->State.ObjCtx);
 }
 
@@ -872,61 +1398,4 @@
 
     return pTransfer->pArea;
-}
-
-/**
- * Returns the current object context of a clipboard URI transfer.
- *
- * @returns Current object context, or NULL if none.
- * @param   pTransfer           URI clipboard transfer to return object context for.
- */
-PSHAREDCLIPBOARDCLIENTURIOBJCTX SharedClipboardURITransferGetCurrentObjCtx(PSHAREDCLIPBOARDURITRANSFER pTransfer)
-{
-    /* At the moment we only have one object context per transfer at a time. */
-    return &pTransfer->State.ObjCtx;
-}
-
-/**
- * Returns the current URI object for a clipboard URI transfer.
- *
- * @returns Current URI object, or NULL if none.
- * @param   pTransfer           URI clipboard transfer to return current URI object for.
- */
-const SharedClipboardURIObject *SharedClipboardURITransferGetCurrentObject(PSHAREDCLIPBOARDURITRANSFER pTransfer)
-{
-    AssertPtrReturn(pTransfer, NULL);
-
-    if (pTransfer->pURIList)
-        return pTransfer->pURIList->First();
-
-    return NULL;
-}
-
-/**
- * Returns the URI list for a clipboard URI transfer.
- *
- * @returns Pointer to URI list.
- * @param   pTransfer           URI clipboard transfer to return URI list for.
- */
-SharedClipboardURIList *SharedClipboardURITransferGetList(PSHAREDCLIPBOARDURITRANSFER pTransfer)
-{
-    AssertPtrReturn(pTransfer, NULL);
-
-    return pTransfer->pURIList;
-}
-
-/**
- * Returns the current URI object for a clipboard URI transfer.
- *
- * @returns Pointer to URI object.
- * @param   pTransfer           URI clipboard transfer to return URI object for.
- */
-SharedClipboardURIObject *SharedClipboardURITransferGetObject(PSHAREDCLIPBOARDURITRANSFER pTransfer, uint64_t uIdx)
-{
-    AssertPtrReturn(pTransfer, NULL);
-
-    if (!pTransfer->pURIList)
-        return NULL;
-
-    return pTransfer->pURIList->At(uIdx);
 }
 
@@ -1051,6 +1520,6 @@
     int rc;
 
-    SharedClipboardURITransferEventMap::iterator itEvent = pTransfer->Events.pMap->find(uID);
-    if (itEvent == pTransfer->Events.pMap->end())
+    SharedClipboardURITransferEventMap::iterator itEvent = pTransfer->pMapEvents->find(uID);
+    if (itEvent == pTransfer->pMapEvents->end())
     {
         PSHAREDCLIPBOARDURITRANSFEREVENT pEvent
@@ -1061,5 +1530,5 @@
             if (RT_SUCCESS(rc))
             {
-                pTransfer->Events.pMap->insert(std::pair<uint32_t, PSHAREDCLIPBOARDURITRANSFEREVENT>(uID, pEvent)); /** @todo Can this throw? */
+                pTransfer->pMapEvents->insert(std::pair<uint32_t, PSHAREDCLIPBOARDURITRANSFEREVENT>(uID, pEvent)); /** @todo Can this throw? */
             }
         }
@@ -1078,6 +1547,6 @@
     int rc;
 
-    SharedClipboardURITransferEventMap::const_iterator itEvent = pTransfer->Events.pMap->find(uID);
-    if (itEvent != pTransfer->Events.pMap->end())
+    SharedClipboardURITransferEventMap::const_iterator itEvent = pTransfer->pMapEvents->find(uID);
+    if (itEvent != pTransfer->pMapEvents->end())
     {
         SharedClipboardURITransferPayloadFree(itEvent->second->pPayload);
@@ -1087,5 +1556,5 @@
         RTMemFree(itEvent->second);
 
-        pTransfer->Events.pMap->erase(itEvent);
+        pTransfer->pMapEvents->erase(itEvent);
 
         rc = VINF_SUCCESS;
@@ -1105,6 +1574,6 @@
     int rc;
 
-    SharedClipboardURITransferEventMap::const_iterator itEvent = pTransfer->Events.pMap->find(uID);
-    if (itEvent != pTransfer->Events.pMap->end())
+    SharedClipboardURITransferEventMap::const_iterator itEvent = pTransfer->pMapEvents->find(uID);
+    if (itEvent != pTransfer->pMapEvents->end())
     {
         rc = RTSemEventWait(itEvent->second->hEventSem, uTimeoutMs);
@@ -1128,6 +1597,6 @@
     int rc;
 
-    SharedClipboardURITransferEventMap::const_iterator itEvent = pTransfer->Events.pMap->find(uID);
-    if (itEvent != pTransfer->Events.pMap->end())
+    SharedClipboardURITransferEventMap::const_iterator itEvent = pTransfer->pMapEvents->find(uID);
+    if (itEvent != pTransfer->pMapEvents->end())
     {
         Assert(itEvent->second->pPayload == NULL);
Index: /trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc-internal.h
===================================================================
--- /trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc-internal.h	(revision 79629)
+++ /trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc-internal.h	(revision 79630)
@@ -150,8 +150,5 @@
     /** Optional protocol version the client uses. Set to 0 by default. */
     uint32_t                 uProtocolVer;
-    /** Flag indicating whether this client currently is deferred mode,
-     *  meaning that it did not return to the caller yet. */
-    bool                     fDeferred;
-    /** Structure for keeping the client's deferred state.
+    /** Structure for keeping the client's pending (deferred return) state.
      *  A client is in a deferred state when it asks for the next HGCM message,
      *  but the service can't provide it yet. That way a client will block (on the guest side, does not return)
@@ -161,5 +158,6 @@
         /** The client's HGCM call handle. Needed for completing a deferred call. */
         VBOXHGCMCALLHANDLE hHandle;
-        /** Message type (function number) to use when completing the deferred call. */
+        /** Message type (function number) to use when completing the deferred call.
+         *  A non-0 value means the client is in pending mode. */
         uint32_t           uType;
         /** Parameter count to use when completing the deferred call. */
@@ -167,5 +165,5 @@
         /** Parameters to use when completing the deferred call. */
         PVBOXHGCMSVCPARM   paParms;
-    } Deferred;
+    } Pending;
 } VBOXCLIPBOARDCLIENT, *PVBOXCLIPBOARDCLIENT;
 
@@ -184,17 +182,13 @@
 int vboxSvcClipboardSetSource(PVBOXCLIPBOARDCLIENTDATA pClientData, SHAREDCLIPBOARDSOURCE enmSource);
 
-int vboxSvcClipboardClientDefer(PVBOXCLIPBOARDCLIENT pClient,
-                                VBOXHGCMCALLHANDLE hHandle, uint32_t u32Function, uint32_t cParms, VBOXHGCMSVCPARM paParms[]);
-int vboxSvcClipboardClientComplete(PVBOXCLIPBOARDCLIENT pClient, VBOXHGCMCALLHANDLE hHandle, int rc);
-int vboxSvcClipboardClientDeferredComplete(PVBOXCLIPBOARDCLIENT pClient, int rc);
-int vboxSvcClipboardClientDeferredSetMsgInfo(PVBOXCLIPBOARDCLIENT pClient, uint32_t uMsg, uint32_t cParms);
-
 void vboxSvcClipboardMsgQueueReset(PVBOXCLIPBOARDCLIENTDATA pClientData);
 PVBOXCLIPBOARDCLIENTMSG vboxSvcClipboardMsgAlloc(uint32_t uMsg, uint32_t cParms);
 void vboxSvcClipboardMsgFree(PVBOXCLIPBOARDCLIENTMSG pMsg);
+void vboxSvcClipboardMsgSetPeekReturn(PVBOXCLIPBOARDCLIENTMSG pMsg, PVBOXHGCMSVCPARM paDstParms, uint32_t cDstParms);
 int vboxSvcClipboardMsgAdd(PVBOXCLIPBOARDCLIENTDATA pClientData, PVBOXCLIPBOARDCLIENTMSG pMsg, bool fAppend);
-int vboxSvcClipboardMsgGetNextInfo(PVBOXCLIPBOARDCLIENTDATA pClientData, uint32_t *puType, uint32_t *pcParms);
-int vboxSvcClipboardMsgGetNext(PVBOXCLIPBOARDCLIENTDATA pClientData,
-                               uint32_t uMsg, uint32_t cParms, VBOXHGCMSVCPARM paParms[]);
+int vboxSvcClipboardMsgPeek(PVBOXCLIPBOARDCLIENT pClient, VBOXHGCMCALLHANDLE hCall, uint32_t cParms, VBOXHGCMSVCPARM paParms[], bool fWait);
+int vboxSvcClipboardMsgGet(PVBOXCLIPBOARDCLIENT pClient, VBOXHGCMCALLHANDLE hCall, uint32_t cParms, VBOXHGCMSVCPARM paParms[]);
+
+int vboxSvcClipboardClientWakeup(PVBOXCLIPBOARDCLIENT pClient);
 
 # ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
@@ -226,13 +220,13 @@
 
 int vboxSvcClipboardURIListOpen(PSHAREDCLIPBOARDPROVIDERCTX pCtx,
-                                PVBOXCLIPBOARDLISTHDR pListHdr, PVBOXCLIPBOARDLISTHANDLE phList);
-int vboxSvcClipboardURIListClose(PSHAREDCLIPBOARDPROVIDERCTX pCtx, VBOXCLIPBOARDLISTHANDLE hList);
-int vboxSvcClipboardURIListHdrRead(PSHAREDCLIPBOARDPROVIDERCTX pCtx, VBOXCLIPBOARDLISTHANDLE hList,
+                                PVBOXCLIPBOARDLISTHDR pListHdr, PSHAREDCLIPBOARDLISTHANDLE phList);
+int vboxSvcClipboardURIListClose(PSHAREDCLIPBOARDPROVIDERCTX pCtx, SHAREDCLIPBOARDLISTHANDLE hList);
+int vboxSvcClipboardURIListHdrRead(PSHAREDCLIPBOARDPROVIDERCTX pCtx, SHAREDCLIPBOARDLISTHANDLE hList,
                                    PVBOXCLIPBOARDLISTHDR pListHdr);
-int vboxSvcClipboardURIListHdrWrite(PSHAREDCLIPBOARDPROVIDERCTX pCtx, VBOXCLIPBOARDLISTHANDLE hList,
+int vboxSvcClipboardURIListHdrWrite(PSHAREDCLIPBOARDPROVIDERCTX pCtx, SHAREDCLIPBOARDLISTHANDLE hList,
                                     PVBOXCLIPBOARDLISTHDR pListHdr);
-int vboxSvcClipboardURIListEntryRead(PSHAREDCLIPBOARDPROVIDERCTX pCtx, VBOXCLIPBOARDLISTHANDLE hList,
+int vboxSvcClipboardURIListEntryRead(PSHAREDCLIPBOARDPROVIDERCTX pCtx, SHAREDCLIPBOARDLISTHANDLE hList,
                                      PVBOXCLIPBOARDLISTENTRY pListEntry);
-int vboxSvcClipboardURIListEntryWrite(PSHAREDCLIPBOARDPROVIDERCTX pCtx, VBOXCLIPBOARDLISTHANDLE hList,
+int vboxSvcClipboardURIListEntryWrite(PSHAREDCLIPBOARDPROVIDERCTX pCtx, SHAREDCLIPBOARDLISTHANDLE hList,
                                       PVBOXCLIPBOARDLISTENTRY pListEntry);
 
Index: /trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc-uri.cpp
===================================================================
--- /trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc-uri.cpp	(revision 79629)
+++ /trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc-uri.cpp	(revision 79630)
@@ -41,6 +41,14 @@
 extern PFNHGCMSVCEXT g_pfnExtension;
 extern void *g_pvExtension;
+extern PVBOXHGCMSVCHELPERS g_pHelpers;
 
 extern ClipboardClientQueue g_listClientsDeferred;
+
+
+/*********************************************************************************************************************************
+*   Prototypes                                                                                                                   *
+*********************************************************************************************************************************/
+int VBoxSvcClipboardURISetListOpen(uint32_t cParms, VBOXHGCMSVCPARM paParms[],
+                                   PVBOXCLIPBOARDLISTOPENPARMS pOpenParms);
 
 
@@ -66,32 +74,7 @@
 
 DECLCALLBACK(int) vboxSvcClipboardURIListOpen(PSHAREDCLIPBOARDPROVIDERCTX pCtx,
-                                              PVBOXCLIPBOARDLISTHDR pListHdr, PVBOXCLIPBOARDLISTHANDLE phList)
-{
-    RT_NOREF(pCtx, pListHdr, phList);
-
-    LogFlowFuncEnter();
-
-    int rc = VINF_SUCCESS;
-
-    LogFlowFuncLeaveRC(rc);
-    return rc;
-}
-
-DECLCALLBACK(int) vboxSvcClipboardURIListClose(PSHAREDCLIPBOARDPROVIDERCTX pCtx, VBOXCLIPBOARDLISTHANDLE hList)
-{
-    RT_NOREF(pCtx, hList);
-
-    LogFlowFuncEnter();
-
-    int rc = VINF_SUCCESS;
-
-    LogFlowFuncLeaveRC(rc);
-    return rc;
-}
-
-DECLCALLBACK(int) vboxSvcClipboardURIListHdrRead(PSHAREDCLIPBOARDPROVIDERCTX pCtx,
-                                                 VBOXCLIPBOARDLISTHANDLE hList, PVBOXCLIPBOARDLISTHDR pListHdr)
-{
-    RT_NOREF(pCtx, hList, pListHdr);
+                                              PVBOXCLIPBOARDLISTOPENPARMS pOpenParms, PSHAREDCLIPBOARDLISTHANDLE phList)
+{
+    RT_NOREF(phList);
 
     LogFlowFuncEnter();
@@ -102,11 +85,20 @@
     int rc;
 
-    PVBOXCLIPBOARDCLIENTMSG pMsg = vboxSvcClipboardMsgAlloc(VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_LIST_HDR_READ,
-                                                            VBOX_SHARED_CLIPBOARD_CPARMS_LIST_HDR_READ);
+    PVBOXCLIPBOARDCLIENTMSG pMsg = vboxSvcClipboardMsgAlloc(VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_LIST_OPEN,
+                                                            VBOX_SHARED_CLIPBOARD_CPARMS_LIST_OPEN);
     if (pMsg)
     {
-        rc = vboxSvcClipboardMsgAdd(&pClient->pData->State, pMsg, true /* fAppend */);
-        if (RT_SUCCESS(rc))
-            rc = vboxSvcClipboardClientDeferredComplete(pClient, VINF_SUCCESS);
+        rc = VBoxSvcClipboardURISetListOpen(pMsg->m_cParms, pMsg->m_paParms, pOpenParms);
+        if (RT_SUCCESS(rc))
+        {
+            rc = vboxSvcClipboardMsgAdd(pClient->pData, pMsg, true /* fAppend */);
+            if (RT_SUCCESS(rc))
+            {
+                int rc2 = SharedClipboardURITransferEventRegister(pCtx->pTransfer, SHAREDCLIPBOARDURITRANSFEREVENTTYPE_LIST_OPEN);
+                AssertRC(rc2);
+
+                vboxSvcClipboardClientWakeup(pClient);
+            }
+        }
     }
     else
@@ -116,12 +108,79 @@
     {
         PSHAREDCLIPBOARDURITRANSFERPAYLOAD pPayload;
-        rc = SharedClipboardURITransferEventWait(pCtx->pTransfer, SHAREDCLIPBOARDURITRANSFEREVENTTYPE_LIST_HDR_READ,
+        rc = SharedClipboardURITransferEventWait(pCtx->pTransfer, SHAREDCLIPBOARDURITRANSFEREVENTTYPE_LIST_OPEN,
                                                  30 * 1000 /* Timeout in ms */, &pPayload);
         if (RT_SUCCESS(rc))
         {
+            Assert(pPayload->cbData == sizeof(VBOXCLIPBOARDREPLY));
+
+            PVBOXCLIPBOARDREPLY pReply = (PVBOXCLIPBOARDREPLY)pPayload->pvData;
+            AssertPtr(pReply);
+
+            Assert(pReply->uType == VBOX_SHAREDCLIPBOARD_REPLYMSGTYPE_LIST_OPEN);
+
+            *phList = pReply->u.ListOpen.uHandle;
+
+            SharedClipboardURITransferPayloadFree(pPayload);
+        }
+    }
+
+    LogFlowFuncLeaveRC(rc);
+    return rc;
+}
+
+DECLCALLBACK(int) vboxSvcClipboardURIListClose(PSHAREDCLIPBOARDPROVIDERCTX pCtx, SHAREDCLIPBOARDLISTHANDLE hList)
+{
+    RT_NOREF(pCtx, hList);
+
+    LogFlowFuncEnter();
+
+    int rc = VINF_SUCCESS;
+
+    LogFlowFuncLeaveRC(rc);
+    return rc;
+}
+
+DECLCALLBACK(int) vboxSvcClipboardURIListHdrRead(PSHAREDCLIPBOARDPROVIDERCTX pCtx,
+                                                 SHAREDCLIPBOARDLISTHANDLE hList, PVBOXCLIPBOARDLISTHDR pListHdr)
+{
+    LogFlowFuncEnter();
+
+    PVBOXCLIPBOARDCLIENT pClient = (PVBOXCLIPBOARDCLIENT)pCtx->pvUser;
+    AssertPtr(pClient);
+
+    int rc;
+
+    PVBOXCLIPBOARDCLIENTMSG pMsg = vboxSvcClipboardMsgAlloc(VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_LIST_HDR_READ,
+                                                            VBOX_SHARED_CLIPBOARD_CPARMS_LIST_HDR_READ_REQ);
+    if (pMsg)
+    {
+        HGCMSvcSetU32(&pMsg->m_paParms[0], 0 /* uContextID */);
+        HGCMSvcSetU64(&pMsg->m_paParms[1], hList);
+        HGCMSvcSetU32(&pMsg->m_paParms[2], 0 /* fFlags */);
+
+        rc = vboxSvcClipboardMsgAdd(pClient->pData, pMsg, true /* fAppend */);
+        if (RT_SUCCESS(rc))
+        {
+            int rc2 = SharedClipboardURITransferEventRegister(pCtx->pTransfer, SHAREDCLIPBOARDURITRANSFEREVENTTYPE_LIST_HDR_WRITE);
+            AssertRC(rc2);
+
+            vboxSvcClipboardClientWakeup(pClient);
+        }
+    }
+    else
+        rc = VERR_NO_MEMORY;
+
+    if (RT_SUCCESS(rc))
+    {
+        PSHAREDCLIPBOARDURITRANSFERPAYLOAD pPayload;
+        rc = SharedClipboardURITransferEventWait(pCtx->pTransfer, SHAREDCLIPBOARDURITRANSFEREVENTTYPE_LIST_HDR_WRITE,
+                                                 30 * 1000 /* Timeout in ms */, &pPayload);
+        if (RT_SUCCESS(rc))
+        {
             Assert(pPayload->cbData == sizeof(VBOXCLIPBOARDLISTHDR));
-            //*ppListHdr = (PVBOXCLIPBOARDLISTHDR)pPayload->pvData;
-
-            RTMemFree(pPayload);
+
+            *pListHdr = *(PVBOXCLIPBOARDLISTHDR)pPayload->pvData;
+
+            SharedClipboardURITransferPayloadFree(pPayload);
         }
     }
@@ -132,5 +191,5 @@
 
 DECLCALLBACK(int) vboxSvcClipboardURIListHdrWrite(PSHAREDCLIPBOARDPROVIDERCTX pCtx,
-                                                  VBOXCLIPBOARDLISTHANDLE hList, PVBOXCLIPBOARDLISTHDR pListHdr)
+                                                  SHAREDCLIPBOARDLISTHANDLE hList, PVBOXCLIPBOARDLISTHDR pListHdr)
 {
     RT_NOREF(pCtx, hList, pListHdr);
@@ -142,31 +201,48 @@
 
 DECLCALLBACK(int) vboxSvcClipboardURIListEntryRead(PSHAREDCLIPBOARDPROVIDERCTX pCtx,
-                                                   VBOXCLIPBOARDLISTHANDLE hList, PVBOXCLIPBOARDLISTENTRY pListEntry)
-{
-    RT_NOREF(pCtx, hList, pListEntry);
-
-    LogFlowFuncEnter();
-
-    PVBOXCLIPBOARDCLIENTDATA pClientData = (PVBOXCLIPBOARDCLIENTDATA)pCtx->pvUser;
-    AssertPtr(pClientData);
-
-    PSHAREDCLIPBOARDURITRANSFERPAYLOAD pPayload;
-    int rc = SharedClipboardURITransferEventWait(pCtx->pTransfer, SHAREDCLIPBOARDURITRANSFEREVENTTYPE_LIST_ENTRY_READ,
+                                                   SHAREDCLIPBOARDLISTHANDLE hList, PVBOXCLIPBOARDLISTENTRY pListEntry)
+{
+    LogFlowFuncEnter();
+
+    PVBOXCLIPBOARDCLIENT pClient = (PVBOXCLIPBOARDCLIENT)pCtx->pvUser;
+    AssertPtr(pClient);
+
+    int rc;
+
+    PVBOXCLIPBOARDCLIENTMSG pMsg = vboxSvcClipboardMsgAlloc(VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_LIST_ENTRY_READ,
+                                                            VBOX_SHARED_CLIPBOARD_CPARMS_LIST_ENTRY_READ_REQ);
+    if (pMsg)
+    {
+        HGCMSvcSetU32(&pMsg->m_paParms[0], 0 /* uContextID */);
+        HGCMSvcSetU64(&pMsg->m_paParms[1], hList);
+        HGCMSvcSetU32(&pMsg->m_paParms[2], 0 /* fInfo */);
+
+        rc = vboxSvcClipboardMsgAdd(pClient->pData, pMsg, true /* fAppend */);
+        if (RT_SUCCESS(rc))
+        {
+            int rc2 = SharedClipboardURITransferEventRegister(pCtx->pTransfer, SHAREDCLIPBOARDURITRANSFEREVENTTYPE_LIST_ENTRY_WRITE);
+            if (rc2 == VERR_ALREADY_EXISTS)
+                rc2 = VINF_SUCCESS;
+            AssertRC(rc2);
+
+            vboxSvcClipboardClientWakeup(pClient);
+        }
+    }
+    else
+        rc = VERR_NO_MEMORY;
+
+    if (RT_SUCCESS(rc))
+    {
+        PSHAREDCLIPBOARDURITRANSFERPAYLOAD pPayload;
+        rc = SharedClipboardURITransferEventWait(pCtx->pTransfer, SHAREDCLIPBOARDURITRANSFEREVENTTYPE_LIST_ENTRY_WRITE,
                                                  30 * 1000 /* Timeout in ms */, &pPayload);
-    if (RT_SUCCESS(rc))
-    {
-        Assert(pPayload->cbData == sizeof(VBOXCLIPBOARDLISTENTRY));
-
-        PVBOXCLIPBOARDLISTENTRY pListEntry = (PVBOXCLIPBOARDLISTENTRY)pPayload->pvData;
-        AssertPtr(pListEntry);
-
-   /*     const uint32_t cbToRead = RT_MIN(cbChunk, pListEntry->cbData);
-
-        memcpy(pvChunk, pListEntry->pvData, cbToRead);*/
-
-        SharedClipboardURITransferPayloadFree(pPayload);
-
-/*        if (pcbRead)
-            *pcbRead = cbToRead;*/
+        if (RT_SUCCESS(rc))
+        {
+            Assert(pPayload->cbData == sizeof(VBOXCLIPBOARDLISTENTRY));
+
+            rc = SharedClipboardURIListEntryCopy(pListEntry, (PVBOXCLIPBOARDLISTENTRY)pPayload->pvData);
+
+            SharedClipboardURITransferPayloadFree(pPayload);
+        }
     }
 
@@ -176,5 +252,5 @@
 
 DECLCALLBACK(int) vboxSvcClipboardURIListEntryWrite(PSHAREDCLIPBOARDPROVIDERCTX pCtx,
-                                                    VBOXCLIPBOARDLISTHANDLE hList, PVBOXCLIPBOARDLISTENTRY pListEntry)
+                                                    SHAREDCLIPBOARDLISTHANDLE hList, PVBOXCLIPBOARDLISTENTRY pListEntry)
 {
     RT_NOREF(pCtx, hList, pListEntry);
@@ -237,34 +313,15 @@
 DECLCALLBACK(void) VBoxSvcClipboardURITransferPrepareCallback(PSHAREDCLIPBOARDURITRANSFERCALLBACKDATA pData)
 {
-    LogFlowFuncEnter();
-
-    AssertPtrReturnVoid(pData);
-
-    PVBOXCLIPBOARDCLIENTDATA pClientData = (PVBOXCLIPBOARDCLIENTDATA)pData->pvUser;
-    AssertPtrReturnVoid(pClientData);
-
-    PSHAREDCLIPBOARDURITRANSFER pTransfer = pData->pTransfer;
-    AssertPtrReturnVoid(pTransfer);
-
-    /* Register needed events. */
-    int rc2 = SharedClipboardURITransferEventRegister(pData->pTransfer, SHAREDCLIPBOARDURITRANSFEREVENTTYPE_LIST_HDR_READ);
-    AssertRC(rc2);
-    rc2 = SharedClipboardURITransferEventRegister(pData->pTransfer, SHAREDCLIPBOARDURITRANSFEREVENTTYPE_LIST_ENTRY_READ);
-    AssertRC(rc2);
-
-#if 0
-    /* Tell the guest that it can start sending URI data. */
-    rc2 = vboxSvcClipboardReportMsg(pClientData, VBOX_SHARED_CLIPBOARD_HOST_MSG_URI_TRANSFER_START,
-                                    0 /* u32Formats == 0 means reading data */);
-    AssertRC(rc2);
-#endif
+    RT_NOREF(pData);
+
+    LogFlowFuncEnter();
 }
 
 DECLCALLBACK(void) VBoxSvcClipboardURITransferCompleteCallback(PSHAREDCLIPBOARDURITRANSFERCALLBACKDATA pData, int rc)
 {
-    LogFlowFuncEnter();
-
     RT_NOREF(pData, rc);
 
+    LogFlowFuncEnter();
+
     LogRel2(("Shared Clipboard: Transfer complete\n"));
 }
@@ -286,4 +343,142 @@
 
     LogRel(("Shared Clipboard: Transfer failed with %Rrc\n", rc));
+}
+
+/**
+ * Gets an URI message reply from HGCM service parameters.
+ *
+ * @returns VBox status code.
+ * @param   cParms              Number of HGCM parameters supplied in \a paParms.
+ * @param   paParms             Array of HGCM parameters.
+ * @param   pReply              Where to store the reply.
+ */
+int VBoxSvcClipboardURIGetReply(uint32_t cParms, VBOXHGCMSVCPARM paParms[],
+                                PVBOXCLIPBOARDREPLY pReply)
+{
+    int rc;
+
+    if (cParms >= VBOX_SHARED_CLIPBOARD_CPARMS_REPLY_MIN)
+    {
+        uint32_t cbPayload = 0;
+
+        /* Note: Context ID (paParms[0]) not used yet. */
+        rc = HGCMSvcGetU32(&paParms[1], &pReply->uType);
+        if (RT_SUCCESS(rc))
+            rc = HGCMSvcGetU32(&paParms[2], &pReply->rc);
+        if (RT_SUCCESS(rc))
+            rc = HGCMSvcGetU32(&paParms[3], &cbPayload);
+        if (RT_SUCCESS(rc))
+        {
+            rc = HGCMSvcGetPv(&paParms[4], &pReply->pvPayload, &pReply->cbPayload);
+            AssertReturn(cbPayload == pReply->cbPayload, VERR_INVALID_PARAMETER);
+        }
+
+        if (RT_SUCCESS(rc))
+        {
+            switch (pReply->uType)
+            {
+                case VBOX_SHAREDCLIPBOARD_REPLYMSGTYPE_LIST_OPEN:
+                {
+                    if (cParms >= 6)
+                    {
+                        rc = HGCMSvcGetU64(&paParms[5], &pReply->u.ListOpen.uHandle);
+                    }
+                    else
+                        rc = VERR_INVALID_PARAMETER;
+                    break;
+                }
+
+                case VBOX_SHAREDCLIPBOARD_REPLYMSGTYPE_OBJ_OPEN:
+                {
+                    if (cParms >= 6)
+                    {
+                        rc = HGCMSvcGetU64(&paParms[5], &pReply->u.ObjOpen.uHandle);
+                    }
+                    else
+                        rc = VERR_INVALID_PARAMETER;
+                    break;
+                }
+
+                default:
+                    break;
+            }
+        }
+    }
+    else
+        rc = VERR_INVALID_PARAMETER;
+
+    LogFlowFuncLeaveRC(rc);
+    return rc;
+}
+
+/**
+ * Gets an URI list open request from HGCM service parameters.
+ *
+ * @returns VBox status code.
+ * @param   cParms              Number of HGCM parameters supplied in \a paParms.
+ * @param   paParms             Array of HGCM parameters.
+ * @param   pOpenParms          Where to store the open parameters of the request.
+ */
+int VBoxSvcClipboardURIGetListOpen(uint32_t cParms, VBOXHGCMSVCPARM paParms[],
+                                   PVBOXCLIPBOARDLISTOPENPARMS pOpenParms)
+{
+    int rc;
+
+    if (cParms == VBOX_SHARED_CLIPBOARD_CPARMS_LIST_OPEN)
+    {
+        uint32_t cbPath   = 0;
+        uint32_t cbFilter = 0;
+
+        /* Note: Context ID (paParms[0]) not used yet. */
+        rc = HGCMSvcGetU32(&paParms[1], &pOpenParms->fList);
+        if (RT_SUCCESS(rc))
+            rc = HGCMSvcGetU32(&paParms[2], &cbPath);
+        if (RT_SUCCESS(rc))
+        {
+            rc = HGCMSvcGetStr(&paParms[3], &pOpenParms->pszPath, &pOpenParms->cbPath);
+            AssertReturn(cbPath == pOpenParms->cbPath, VERR_INVALID_PARAMETER);
+        }
+        if (RT_SUCCESS(rc))
+            rc = HGCMSvcGetU32(&paParms[4], &cbFilter);
+        if (RT_SUCCESS(rc))
+        {
+            rc = HGCMSvcGetStr(&paParms[5], &pOpenParms->pszFilter, &pOpenParms->cbFilter);
+            AssertReturn(cbFilter == pOpenParms->cbFilter, VERR_INVALID_PARAMETER);
+        }
+
+        if (RT_SUCCESS(rc))
+        {
+            /** @todo Some more validation. */
+        }
+    }
+    else
+        rc = VERR_INVALID_PARAMETER;
+
+    LogFlowFuncLeaveRC(rc);
+    return rc;
+}
+
+int VBoxSvcClipboardURISetListOpen(uint32_t cParms, VBOXHGCMSVCPARM paParms[],
+                                   PVBOXCLIPBOARDLISTOPENPARMS pOpenParms)
+{
+    int rc;
+
+    if (cParms == VBOX_SHARED_CLIPBOARD_CPARMS_LIST_OPEN)
+    {
+        HGCMSvcSetU32(&paParms[0], 0 /* uContextID */);
+        HGCMSvcSetU32(&paParms[1], pOpenParms->fList);
+        HGCMSvcSetU32(&paParms[2], pOpenParms->cbFilter);
+        HGCMSvcSetPv (&paParms[3], pOpenParms->pszFilter, pOpenParms->cbFilter);
+        HGCMSvcSetU32(&paParms[4], pOpenParms->cbPath);
+        HGCMSvcSetPv (&paParms[5], pOpenParms->pszPath, pOpenParms->cbPath);
+        HGCMSvcSetU64(&paParms[6], 0); /* OUT: uHandle */
+
+        rc = VINF_SUCCESS;
+    }
+    else
+        rc = VERR_INVALID_PARAMETER;
+
+    LogFlowFuncLeaveRC(rc);
+    return rc;
 }
 
@@ -298,20 +493,23 @@
  */
 int VBoxSvcClipboardURIGetListHdr(uint32_t cParms, VBOXHGCMSVCPARM paParms[],
-                                  PVBOXCLIPBOARDLISTHANDLE phList, PVBOXCLIPBOARDLISTHDR pListHdr)
+                                  PSHAREDCLIPBOARDLISTHANDLE phList, PVBOXCLIPBOARDLISTHDR pListHdr)
 {
     int rc;
 
-    if (cParms == VBOX_SHARED_CLIPBOARD_CPARMS_LIST_HDR_WRITE)
+    if (cParms == VBOX_SHARED_CLIPBOARD_CPARMS_LIST_HDR)
     {
         /* Note: Context ID (paParms[0]) not used yet. */
         rc = HGCMSvcGetU64(&paParms[1], phList);
-        if (RT_SUCCESS(rc))
-            rc = HGCMSvcGetU64(&paParms[2], &pListHdr->cTotalObjects);
-        if (RT_SUCCESS(rc))
-            rc = HGCMSvcGetU64(&paParms[3], &pListHdr->cbTotalSize);
-        if (RT_SUCCESS(rc))
-            rc = HGCMSvcGetU32(&paParms[4], &pListHdr->enmCompression);
-        if (RT_SUCCESS(rc))
-            rc = HGCMSvcGetU32(&paParms[5], (uint32_t *)&pListHdr->enmChecksumType);
+        /* Note: Flags (paParms[2]) not used here. */
+        if (RT_SUCCESS(rc))
+            rc = HGCMSvcGetU32(&paParms[3], &pListHdr->fFeatures);
+        if (RT_SUCCESS(rc))
+            rc = HGCMSvcGetU64(&paParms[4], &pListHdr->cTotalObjects);
+        if (RT_SUCCESS(rc))
+            rc = HGCMSvcGetU64(&paParms[5], &pListHdr->cbTotalSize);
+        if (RT_SUCCESS(rc))
+            rc = HGCMSvcGetU32(&paParms[6], &pListHdr->enmCompression);
+        if (RT_SUCCESS(rc))
+            rc = HGCMSvcGetU32(&paParms[7], (uint32_t *)&pListHdr->enmChecksumType);
 
         if (RT_SUCCESS(rc))
@@ -340,18 +538,17 @@
     int rc;
 
-    if (cParms == VBOX_SHARED_CLIPBOARD_CPARMS_LIST_HDR_READ)
+    if (   cParms == VBOX_SHARED_CLIPBOARD_CPARMS_LIST_HDR
+        || cParms == VBOX_SHARED_CLIPBOARD_CPARMS_LIST_HDR)
     {
         /** @todo Set pvMetaFmt + cbMetaFmt. */
         /** @todo Calculate header checksum. */
 
-        /* Note: Context ID (paParms[0]) not used yet. */
-        HGCMSvcSetU32(&paParms[1], pListHdr->fList);
-        HGCMSvcSetU32(&paParms[2], pListHdr->fFeatures);
-        HGCMSvcSetU32(&paParms[3], pListHdr->cbFilter);
-        HGCMSvcSetPv (&paParms[4], pListHdr->pszFilter, pListHdr->cbFilter);
-        HGCMSvcSetU64(&paParms[5], pListHdr->cTotalObjects);
-        HGCMSvcSetU64(&paParms[6], pListHdr->cbTotalSize);
-        HGCMSvcSetU32(&paParms[7], pListHdr->enmCompression);
-        HGCMSvcSetU32(&paParms[8], (uint32_t)pListHdr->enmChecksumType);
+        HGCMSvcSetU32(&paParms[0], 0 /* uContextID */);
+        HGCMSvcSetU32(&paParms[1], pListHdr->fFeatures);
+        HGCMSvcSetU32(&paParms[2], 0 /* Features, will be returned on success */);
+        HGCMSvcSetU64(&paParms[3], pListHdr->cTotalObjects);
+        HGCMSvcSetU64(&paParms[4], pListHdr->cbTotalSize);
+        HGCMSvcSetU32(&paParms[5], pListHdr->enmCompression);
+        HGCMSvcSetU32(&paParms[6], pListHdr->enmChecksumType);
 
         rc = VINF_SUCCESS;
@@ -374,9 +571,9 @@
  */
 int VBoxSvcClipboardURIGetListEntry(uint32_t cParms, VBOXHGCMSVCPARM paParms[],
-                                    PVBOXCLIPBOARDLISTHANDLE phList, PVBOXCLIPBOARDLISTENTRY pListEntry)
+                                    PSHAREDCLIPBOARDLISTHANDLE phList, PVBOXCLIPBOARDLISTENTRY pListEntry)
 {
     int rc;
 
-    if (cParms == VBOX_SHARED_CLIPBOARD_CPARMS_LIST_ENTRY_WRITE)
+    if (cParms == VBOX_SHARED_CLIPBOARD_CPARMS_LIST_ENTRY)
     {
         /* Note: Context ID (paParms[0]) not used yet. */
@@ -414,9 +611,9 @@
     int rc;
 
-    if (cParms == VBOX_SHARED_CLIPBOARD_CPARMS_LIST_ENTRY_READ)
+    if (cParms == VBOX_SHARED_CLIPBOARD_CPARMS_LIST_ENTRY)
     {
         /** @todo Calculate chunk checksum. */
 
-        /* Note: Context ID (paParms[0]) not used yet. */
+        HGCMSvcSetU32(&paParms[0], 0 /* uContextID */);
         HGCMSvcSetU32(&paParms[1], pListEntry->fInfo);
         HGCMSvcSetU32(&paParms[2], pListEntry->cbInfo);
@@ -432,4 +629,12 @@
 }
 
+/**
+ * Gets an URI error from HGCM service parameters.
+ *
+ * @returns VBox status code.
+ * @param   cParms              Number of HGCM parameters supplied in \a paParms.
+ * @param   paParms             Array of HGCM parameters.
+ * @param   pRc                 Where to store the received error code.
+ */
 int VBoxSvcClipboardURIGetError(uint32_t cParms, VBOXHGCMSVCPARM paParms[], int *pRc)
 {
@@ -446,4 +651,62 @@
     else
         rc = VERR_INVALID_PARAMETER;
+
+    LogFlowFuncLeaveRC(rc);
+    return rc;
+}
+
+int VBoxSvcClipboardURITransferHandleReply(PVBOXCLIPBOARDCLIENT pClient, PSHAREDCLIPBOARDURITRANSFER pTransfer,
+                                           uint32_t cParms, VBOXHGCMSVCPARM paParms[])
+{
+    RT_NOREF(pClient);
+
+    int rc;
+
+    uint32_t            cbReply = sizeof(VBOXCLIPBOARDREPLY);
+    PVBOXCLIPBOARDREPLY pReply  = (PVBOXCLIPBOARDREPLY)RTMemAlloc(cbReply);
+    if (pReply)
+    {
+        rc = VBoxSvcClipboardURIGetReply(cParms, paParms, pReply);
+        if (RT_SUCCESS(rc))
+        {
+            PSHAREDCLIPBOARDURITRANSFERPAYLOAD pPayload
+                = (PSHAREDCLIPBOARDURITRANSFERPAYLOAD)RTMemAlloc(sizeof(SHAREDCLIPBOARDURITRANSFERPAYLOAD));
+            if (pPayload)
+            {
+                pPayload->pvData = pReply;
+                pPayload->cbData = cbReply;
+
+                switch (pReply->uType)
+                {
+                    case VBOX_SHAREDCLIPBOARD_REPLYMSGTYPE_LIST_OPEN:
+                    {
+                        rc = SharedClipboardURITransferEventSignal(pTransfer,
+                                                                   SHAREDCLIPBOARDURITRANSFEREVENTTYPE_LIST_OPEN, pPayload);
+                        break;
+                    }
+
+                    default:
+                        rc = VERR_NOT_FOUND;
+                        break;
+                }
+
+                if (RT_FAILURE(rc))
+                {
+                    if (pPayload)
+                        RTMemFree(pPayload);
+                }
+            }
+            else
+                rc = VERR_NO_MEMORY;
+        }
+    }
+    else
+        rc = VERR_NO_MEMORY;
+
+    if (RT_FAILURE(rc))
+    {
+        if (pReply)
+            RTMemFree(pReply);
+    }
 
     LogFlowFuncLeaveRC(rc);
@@ -471,6 +734,6 @@
     RT_NOREF(paParms, tsArrival);
 
-    LogFlowFunc(("uClient=%RU32, u32Function=%RU32, cParms=%RU32, g_pfnExtension=%p\n",
-                 pClient->uClientID, u32Function, cParms, g_pfnExtension));
+    LogFlowFunc(("uClient=%RU32, u32Function=%RU32 (%s), cParms=%RU32, g_pfnExtension=%p\n",
+                 pClient->uClientID, u32Function, VBoxSvcClipboardGuestMsgToStr(u32Function), cParms, g_pfnExtension));
 
     const PVBOXCLIPBOARDCLIENTDATA pClientData = pClient->pData;
@@ -503,7 +766,11 @@
     switch (u32Function)
     {
-        case VBOX_SHARED_CLIPBOARD_GUEST_FN_GET_HOST_MSG:
+        case VBOX_SHARED_CLIPBOARD_GUEST_FN_MSG_PEEK_NOWAIT:
             RT_FALL_THROUGH();
-        case VBOX_SHARED_CLIPBOARD_GUEST_FN_TRANSFER_REPORT:
+        case VBOX_SHARED_CLIPBOARD_GUEST_FN_MSG_PEEK_WAIT:
+            RT_FALL_THROUGH();
+        case VBOX_SHARED_CLIPBOARD_GUEST_FN_MSG_GET:
+            RT_FALL_THROUGH();
+        case VBOX_SHARED_CLIPBOARD_GUEST_FN_STATUS:
             break;
         default:
@@ -535,9 +802,20 @@
     switch (u32Function)
     {
-        case VBOX_SHARED_CLIPBOARD_GUEST_FN_TRANSFER_REPORT:
-        {
-            LogFlowFunc(("VBOX_SHARED_CLIPBOARD_GUEST_FN_TRANSFER_REPORT\n"));
-
-            if (!SharedClipboardURICtxTransfersMaximumReached(&pClientData->URI))
+        case VBOX_SHARED_CLIPBOARD_GUEST_FN_STATUS:
+        {
+            LogFlowFunc(("[Client %RU32] VBOX_SHARED_CLIPBOARD_GUEST_FN_STATUS\n", pClient->uClientID));
+
+            if (cParms != VBOX_SHARED_CLIPBOARD_CPARMS_STATUS)
+                break;
+
+            SHAREDCLIPBOARDURITRANSFERSTATUS uStatus = SHAREDCLIPBOARDURITRANSFERSTATUS_NONE;
+            rc = HGCMSvcGetU32(&paParms[1], &uStatus);
+            if (RT_FAILURE(rc))
+                break;
+
+            LogFlowFunc(("uStatus: %RU32\n", uStatus));
+
+            if (   uStatus == SHAREDCLIPBOARDURITRANSFERSTATUS_RUNNING
+                && !SharedClipboardURICtxTransfersMaximumReached(&pClientData->URI))
             {
                 SharedClipboardURICtxTransfersCleanup(&pClientData->URI);
@@ -592,5 +870,5 @@
                         SharedClipboardURITransferSetCallbacks(pTransfer, &Callbacks);
 
-                        rc = SharedClipboardURITransferProviderCreate(pTransfer, &creationCtx);
+                        rc = SharedClipboardURITransferSetInterface(pTransfer, &creationCtx);
                         if (RT_SUCCESS(rc))
                             rc = SharedClipboardURICtxTransferAdd(&pClientData->URI, pTransfer);
@@ -614,5 +892,5 @@
                 rc = VERR_SHCLPB_MAX_TRANSFERS_REACHED;
 
-            LogFunc(("VBOX_SHARED_CLIPBOARD_GUEST_FN_TRANSFER_REPORT: %Rrc\n", rc));
+            LogFlowFunc(("[Client %RU32] VBOX_SHARED_CLIPBOARD_GUEST_FN_STATUS: %Rrc\n", pClient->uClientID, rc));
 
             if (RT_FAILURE(rc))
@@ -622,28 +900,40 @@
         }
 
-        case VBOX_SHARED_CLIPBOARD_GUEST_FN_GET_HOST_MSG:
-        {
-            if (cParms == VBOX_SHARED_CLIPBOARD_CPARMS_GET_HOST_MSG)
-            {
-                LogFlowFunc(("VBOX_SHARED_CLIPBOARD_GUEST_FN_GET_HOST_MSG\n"));
-                rc = vboxSvcClipboardMsgGetNextInfo(&pClientData->State,
-                                                    &paParms[0].u.uint32 /* uMsg */, &paParms[1].u.uint32 /* cParms */);
-
-                /* No (new) messages available or some error occurred? */
-                if (   rc == VERR_NO_DATA
-                    || RT_FAILURE(rc))
+        case VBOX_SHARED_CLIPBOARD_GUEST_FN_MSG_PEEK_NOWAIT:
+        {
+            rc = vboxSvcClipboardMsgPeek(pClient, callHandle, cParms, paParms, false /*fWait*/);
+            break;
+        }
+
+        case VBOX_SHARED_CLIPBOARD_GUEST_FN_MSG_PEEK_WAIT:
+        {
+            rc = vboxSvcClipboardMsgPeek(pClient, callHandle, cParms, paParms, true /*fWait*/);
+            break;
+        }
+
+        case VBOX_SHARED_CLIPBOARD_GUEST_FN_MSG_GET:
+        {
+            rc = vboxSvcClipboardMsgGet(pClient, callHandle, cParms, paParms);
+            break;
+        }
+
+        case VBOX_SHARED_CLIPBOARD_GUEST_FN_REPLY:
+        {
+            rc = VBoxSvcClipboardURITransferHandleReply(pClient, pTransfer, cParms, paParms);
+            break;
+        }
+
+        case VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_OPEN:
+        {
+            VBOXCLIPBOARDLISTOPENPARMS listOpenParms;
+            rc = VBoxSvcClipboardURIGetListOpen(cParms, paParms, &listOpenParms);
+            if (RT_SUCCESS(rc))
+            {
+                SHAREDCLIPBOARDLISTHANDLE hList;
+                rc = SharedClipboardURITransferListOpen(pTransfer, &listOpenParms, &hList);
+                if (RT_SUCCESS(rc))
                 {
-                    uint32_t fFlags = 0;
-                    int rc2 = HGCMSvcGetU32(&paParms[2], &fFlags);
-                    if (   RT_SUCCESS(rc2)
-                        && fFlags) /* Blocking flag set? */
-                    {
-                        /* Defer client returning. */
-                        rc = VINF_HGCM_ASYNC_EXECUTE;
-                    }
-                    else
-                        rc = VERR_INVALID_PARAMETER;
-
-                    LogFlowFunc(("Message queue is empty, returning %Rrc to guest\n", rc));
+                    /* Return list handle. */
+                    HGCMSvcSetU32(&paParms[1], hList);
                 }
             }
@@ -651,15 +941,16 @@
         }
 
-        case VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_OPEN:
-        {
-            LogFlowFunc(("VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_OPEN\n"));
-            rc = VINF_SUCCESS;
-            break;
-        }
-
         case VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_CLOSE:
         {
-            LogFlowFunc(("VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_CLOSE\n"));
-            rc = VINF_SUCCESS;
+            if (cParms != VBOX_SHARED_CLIPBOARD_CPARMS_LIST_CLOSE)
+                break;
+
+            SHAREDCLIPBOARDLISTHANDLE hList;
+            /* Note: Context ID (paParms[0]) not used yet. */
+            rc = HGCMSvcGetU64(&paParms[1], &hList);
+            if (RT_SUCCESS(rc))
+            {
+                rc = SharedClipboardURITransferListClose(pTransfer, hList);
+            }
             break;
         }
@@ -667,11 +958,14 @@
         case VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_HDR_READ:
         {
-            LogFlowFunc(("VBOX_SHARED_CLIPBOARD_GUEST_FN_READ_LIST_HDR\n"));
-
-            VBOXCLIPBOARDLISTHANDLE hList;
-            VBOXCLIPBOARDLISTHDR    hdrList;
-            rc = VBoxSvcClipboardURIGetListHdr(cParms, paParms, &hList, &hdrList);
+            if (cParms != VBOX_SHARED_CLIPBOARD_CPARMS_LIST_HDR)
+                break;
+
+            SHAREDCLIPBOARDLISTHANDLE hList;
+            /* Note: Context ID (paParms[0]) not used yet. */
+            rc = HGCMSvcGetU64(&paParms[1], &hList); /* Get list handle. */
             if (RT_SUCCESS(rc))
             {
+                VBOXCLIPBOARDLISTHDR hdrList;
+                rc = SharedClipboardURITransferListGetHeader(pTransfer, hList, &hdrList);
                 if (RT_SUCCESS(rc))
                     rc = VBoxSvcClipboardURISetListHdr(cParms, paParms, &hdrList);
@@ -682,11 +976,9 @@
         case VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_HDR_WRITE:
         {
-            LogFlowFunc(("VBOX_SHARED_CLIPBOARD_GUEST_FN_WRITE_LIST_HDR\n"));
-
             VBOXCLIPBOARDLISTHDR hdrList;
             rc = SharedClipboardURIListHdrInit(&hdrList);
             if (RT_SUCCESS(rc))
             {
-                VBOXCLIPBOARDLISTHANDLE hList;
+                SHAREDCLIPBOARDLISTHANDLE hList;
                 rc = VBoxSvcClipboardURIGetListHdr(cParms, paParms, &hList, &hdrList);
                 if (RT_SUCCESS(rc))
@@ -696,9 +988,9 @@
 
                     PSHAREDCLIPBOARDURITRANSFERPAYLOAD pPayload;
-                    rc = SharedClipboardURITransferPayloadAlloc(SHAREDCLIPBOARDURITRANSFEREVENTTYPE_LIST_HDR_READ,
+                    rc = SharedClipboardURITransferPayloadAlloc(SHAREDCLIPBOARDURITRANSFEREVENTTYPE_LIST_HDR_WRITE,
                                                                 pvData, cbData, &pPayload);
                     if (RT_SUCCESS(rc))
                     {
-                        rc = SharedClipboardURITransferEventSignal(pTransfer, SHAREDCLIPBOARDURITRANSFEREVENTTYPE_LIST_HDR_READ,
+                        rc = SharedClipboardURITransferEventSignal(pTransfer, SHAREDCLIPBOARDURITRANSFEREVENTTYPE_LIST_HDR_WRITE,
                                                                    pPayload);
                     }
@@ -710,5 +1002,15 @@
         case VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_ENTRY_READ:
         {
-            LogFlowFunc(("VBOX_SHARED_CLIPBOARD_GUEST_FN_READ_LIST_ENTRY\n"));
+            if (cParms != VBOX_SHARED_CLIPBOARD_CPARMS_LIST_ENTRY)
+                break;
+
+            SHAREDCLIPBOARDLISTHANDLE hList;
+            /* Note: Context ID (paParms[0]) not used yet. */
+            rc = HGCMSvcGetU64(&paParms[1], &hList); /* Get list handle. */
+            if (RT_SUCCESS(rc))
+            {
+                VBOXCLIPBOARDLISTENTRY entryList;
+                rc = SharedClipboardURITransferListRead(pTransfer, hList, &entryList);
+            }
             break;
         }
@@ -716,11 +1018,9 @@
         case VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_ENTRY_WRITE:
         {
-            LogFlowFunc(("VBOX_SHARED_CLIPBOARD_GUEST_FN_WRITE_LIST_ENTRY\n"));
-
             VBOXCLIPBOARDLISTENTRY entryList;
             rc = SharedClipboardURIListEntryInit(&entryList);
             if (RT_SUCCESS(rc))
             {
-                VBOXCLIPBOARDLISTHANDLE hList;
+                SHAREDCLIPBOARDLISTHANDLE hList;
                 rc = VBoxSvcClipboardURIGetListEntry(cParms, paParms, &hList, &entryList);
                 if (RT_SUCCESS(rc))
@@ -730,9 +1030,9 @@
 
                     PSHAREDCLIPBOARDURITRANSFERPAYLOAD pPayload;
-                    rc = SharedClipboardURITransferPayloadAlloc(SHAREDCLIPBOARDURITRANSFEREVENTTYPE_LIST_ENTRY_READ,
+                    rc = SharedClipboardURITransferPayloadAlloc(SHAREDCLIPBOARDURITRANSFEREVENTTYPE_LIST_ENTRY_WRITE,
                                                                 pvData, cbData, &pPayload);
                     if (RT_SUCCESS(rc))
                     {
-                        rc = SharedClipboardURITransferEventSignal(pTransfer, SHAREDCLIPBOARDURITRANSFEREVENTTYPE_LIST_ENTRY_READ,
+                        rc = SharedClipboardURITransferEventSignal(pTransfer, SHAREDCLIPBOARDURITRANSFEREVENTTYPE_LIST_ENTRY_WRITE,
                                                                    pPayload);
                     }
@@ -742,5 +1042,6 @@
             break;
         }
-#if 0
+
+    #if 0
         case VBOX_SHARED_CLIPBOARD_GUEST_FN_WRITE_DIR:
         {
@@ -913,13 +1214,11 @@
 #endif
         case VBOX_SHARED_CLIPBOARD_GUEST_FN_CANCEL:
-            LogFlowFunc(("VBOX_SHARED_CLIPBOARD_FN_CANCEL\n"));
-
+        {
             LogRel2(("Shared Clipboard: Transfer canceled\n"));
             break;
+        }
 
         case VBOX_SHARED_CLIPBOARD_GUEST_FN_ERROR:
         {
-            LogFlowFunc(("VBOX_SHARED_CLIPBOARD_FN_ERROR\n"));
-
             int rcGuest;
             rc = VBoxSvcClipboardURIGetError(cParms,paParms, &rcGuest);
@@ -930,28 +1229,17 @@
 
         default:
-            AssertMsgFailed(("Not implemented\n"));
-            break;
-    }
-
-    if (rc == VINF_HGCM_ASYNC_EXECUTE)
-    {
-        try
-        {
-            vboxSvcClipboardClientDefer(pClient, callHandle, u32Function, cParms, paParms);
-            g_listClientsDeferred.push_back(pClient->uClientID);
-        }
-        catch (std::bad_alloc &)
-        {
-            rc = VERR_NO_MEMORY;
-            /* Don't report to guest. */
-        }
-    }
-    else if (pClient)
-    {
-        int rc2 = vboxSvcClipboardClientComplete(pClient, callHandle, rc);
-        AssertRC(rc2);
-    }
-
-    LogFlowFunc(("Returning uClient=%RU32, rc=%Rrc\n", pClient->uClientID, rc));
+            LogFunc(("Not implemented\n"));
+            break;
+    }
+
+    if (rc != VINF_HGCM_ASYNC_EXECUTE)
+    {
+        /* Tell the client that the call is complete (unblocks waiting). */
+        LogFlowFunc(("[Client %RU32] Calling pfnCallComplete w/ rc=%Rrc\n", pClient->uClientID, rc));
+        AssertPtr(g_pHelpers);
+        g_pHelpers->pfnCallComplete(callHandle, rc);
+    }
+
+    LogFlowFunc(("[Client %RU32] Returning rc=%Rrc\n", pClient->uClientID, rc));
     return rc;
 }
Index: /trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc-utils.cpp
===================================================================
--- /trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc-utils.cpp	(revision 79629)
+++ /trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc-utils.cpp	(revision 79630)
@@ -68,15 +68,11 @@
             break;
 
-        case VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_HDR_WRITE:
-            RT_FALL_THROUGH();
-        case VBOX_SHARED_CLIPBOARD_GUEST_FN_LIST_ENTRY_WRITE:
-            RT_FALL_THROUGH();
-        case VBOX_SHARED_CLIPBOARD_GUEST_FN_OBJ_WRITE:
-            fAllowed = fGuestToHost;
-            break;
-
-        case VBOX_SHARED_CLIPBOARD_GUEST_FN_TRANSFER_REPORT:
-            RT_FALL_THROUGH();
-        case VBOX_SHARED_CLIPBOARD_GUEST_FN_GET_HOST_MSG:
+        case VBOX_SHARED_CLIPBOARD_GUEST_FN_MSG_PEEK_WAIT:
+            RT_FALL_THROUGH();
+        case VBOX_SHARED_CLIPBOARD_GUEST_FN_MSG_PEEK_NOWAIT:
+            RT_FALL_THROUGH();
+        case VBOX_SHARED_CLIPBOARD_GUEST_FN_MSG_GET:
+            RT_FALL_THROUGH();
+        case VBOX_SHARED_CLIPBOARD_GUEST_FN_STATUS:
             RT_FALL_THROUGH();
         case VBOX_SHARED_CLIPBOARD_GUEST_FN_CANCEL:
@@ -89,4 +85,6 @@
             break;
     }
+
+    fAllowed = true; /** @todo FIX !!!! */
 
     LogFlowFunc(("uMsg=%RU32, uMode=%RU32 -> fAllowed=%RTbool\n", uMsg, uMode, fAllowed));
Index: /trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc-win.cpp
===================================================================
--- /trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc-win.cpp	(revision 79629)
+++ /trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc-win.cpp	(revision 79630)
@@ -646,5 +646,5 @@
     {
         if (pCtx->Win.hWnd)
-            PostMessage(pCtx->Win.hWnd, WM_CLOSE, 0 /* wParam */, 0 /* lParam */);
+            PostMessage(pCtx->Win.hWnd, WM_DESTROY, 0 /* wParam */, 0 /* lParam */);
 
         rc = RTSemEventDestroy(pCtx->hRenderEvent);
Index: /trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc.cpp
===================================================================
--- /trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc.cpp	(revision 79629)
+++ /trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc.cpp	(revision 79630)
@@ -127,4 +127,22 @@
  * the rest of the code stays the same.
  *
+ * @section sec_uri_protocol            URI protocol.
+ *
+ * The host service issues commands which the guest has to respond with an own
+ * message to. The protocol itself is designed so that it has primitives to list
+ * directories and open/close/read/write file system objects.
+ *
+ * The protocol does not rely on the old ReportMsg() / ReturnMsg() mechanism anymore
+ * and uses a (per-client) message queue instead (see VBOX_SHARED_CLIPBOARD_GUEST_FN_GET_HOST_MSG_OLD
+ * vs. VBOX_SHARED_CLIPBOARD_GUEST_FN_GET_HOST_MSG).
+ *
+ * Note that this is different from the DnD approach, as Shared Clipboard transfers
+ * need to be deeper integrated within the host / guest OS (i.e. for progress UI),
+ * and this might require non-monolithic / random access APIs to achieve.
+ *
+ * One transfer always is handled by an own (HGCM) client, so for multiple transfers
+ * at the same time, multiple clients (client IDs) are being used. How this transfer
+ * is implemented on the guest (and / or host) side depends upon the actual implementation,
+ * e.g. via an own thread per transfer.
  */
 
@@ -136,4 +154,5 @@
 #include <VBox/log.h>
 
+#include <VBox/AssertGuest.h>
 #include <VBox/HostServices/Service.h>
 #include <VBox/HostServices/VBoxClipboardSvc.h>
@@ -167,5 +186,5 @@
 *   Global Variables                                                                                                             *
 *********************************************************************************************************************************/
-static PVBOXHGCMSVCHELPERS g_pHelpers;
+PVBOXHGCMSVCHELPERS g_pHelpers;
 
 static RTCRITSECT g_CritSect;
@@ -183,20 +202,11 @@
 static bool g_fHeadless = false;
 
-/** Map of all connected clients. */
+/** Global map of all connected clients. */
 ClipboardClientMap g_mapClients;
 
-/** List of all clients which are queued up (deferred return) and ready
+/** Global list of all clients which are queued up (deferred return) and ready
  *  to process new commands. The key is the (unique) client ID. */
 ClipboardClientQueue g_listClientsDeferred;
 
-
-#if 0
-static void VBoxHGCMParmPtrSet (VBOXHGCMSVCPARM *pParm, void *pv, uint32_t cb)
-{
-    pParm->type             = VBOX_HGCM_SVC_PARM_PTR;
-    pParm->u.pointer.size   = cb;
-    pParm->u.pointer.addr   = pv;
-}
-#endif
 
 static int VBoxHGCMParmPtrGet(VBOXHGCMSVCPARM *pParm, void **ppv, uint32_t *pcb)
@@ -323,4 +333,30 @@
 
 /**
+ * Sets the GUEST_MSG_PEEK_WAIT GUEST_MSG_PEEK_NOWAIT return parameters.
+ *
+ * @param   paDstParms  The peek parameter vector.
+ * @param   cDstParms   The number of peek parameters (at least two).
+ * @remarks ASSUMES the parameters has been cleared by clientMsgPeek.
+ */
+void vboxSvcClipboardMsgSetPeekReturn(PVBOXCLIPBOARDCLIENTMSG pMsg, PVBOXHGCMSVCPARM paDstParms, uint32_t cDstParms)
+{
+    Assert(cDstParms >= 2);
+    if (paDstParms[0].type == VBOX_HGCM_SVC_PARM_32BIT)
+        paDstParms[0].u.uint32 = pMsg->m_uMsg;
+    else
+        paDstParms[0].u.uint64 = pMsg->m_uMsg;
+    paDstParms[1].u.uint32 = pMsg->m_cParms;
+
+    uint32_t i = RT_MIN(cDstParms, pMsg->m_cParms + 2);
+    while (i-- > 2)
+        switch (pMsg->m_paParms[i - 2].type)
+        {
+            case VBOX_HGCM_SVC_PARM_32BIT: paDstParms[i].u.uint32 = ~(uint32_t)sizeof(uint32_t); break;
+            case VBOX_HGCM_SVC_PARM_64BIT: paDstParms[i].u.uint32 = ~(uint32_t)sizeof(uint64_t); break;
+            case VBOX_HGCM_SVC_PARM_PTR:   paDstParms[i].u.uint32 = pMsg->m_paParms[i - 2].u.pointer.size; break;
+        }
+}
+
+/**
  * Adds a new message to a client'S message queue.
  *
@@ -347,89 +383,254 @@
 
 /**
- * Retrieves information about the next message in the queue.
- *
- * @returns IPRT status code. VERR_NO_DATA if no next message is available.
- * @param   pClientData         Pointer to the client data structure to get message info for.
- * @param   puType              Where to store the message type.
- * @param   pcParms             Where to store the message parameter count.
+ * Implements VBOX_SHARED_CLIPBOARD_GUEST_FN_MSG_PEEK_WAIT and VBOX_SHARED_CLIPBOARD_GUEST_FN_MSG_PEEK_NOWAIT.
+ *
+ * @returns VBox status code.
+ * @retval  VINF_SUCCESS if a message was pending and is being returned.
+ * @retval  VERR_TRY_AGAIN if no message pending and not blocking.
+ * @retval  VERR_RESOURCE_BUSY if another read already made a waiting call.
+ * @retval  VINF_HGCM_ASYNC_EXECUTE if message wait is pending.
+ *
+ * @param   pClient     The client state.
+ * @param   hCall       The client's call handle.
+ * @param   cParms      Number of parameters.
+ * @param   paParms     Array of parameters.
+ * @param   fWait       Set if we should wait for a message, clear if to return
+ *                      immediately.
  */
-int vboxSvcClipboardMsgGetNextInfo(PVBOXCLIPBOARDCLIENTDATA pClientData, uint32_t *puType, uint32_t *pcParms)
-{
-    AssertPtrReturn(puType, VERR_INVALID_POINTER);
-    AssertPtrReturn(pcParms, VERR_INVALID_POINTER);
-
-    int rc;
-
-    if (pClientData->queueMsg.isEmpty())
-    {
-        rc = VERR_NO_DATA;
-    }
-    else
-    {
-        PVBOXCLIPBOARDCLIENTMSG pMsg = pClientData->queueMsg.first();
-        AssertPtr(pMsg);
-
-        *puType  = pMsg->m_uMsg;
-        *pcParms = pMsg->m_cParms;
+int vboxSvcClipboardMsgPeek(PVBOXCLIPBOARDCLIENT pClient, VBOXHGCMCALLHANDLE hCall, uint32_t cParms, VBOXHGCMSVCPARM paParms[],
+                            bool fWait)
+{
+    /*
+     * Validate the request.
+     */
+    ASSERT_GUEST_MSG_RETURN(cParms >= 2, ("cParms=%u!\n", cParms), VERR_WRONG_PARAMETER_COUNT);
+
+    uint64_t idRestoreCheck = 0;
+    uint32_t i              = 0;
+    if (paParms[i].type == VBOX_HGCM_SVC_PARM_64BIT)
+    {
+        idRestoreCheck = paParms[0].u.uint64;
+        paParms[0].u.uint64 = 0;
+        i++;
+    }
+    for (; i < cParms; i++)
+    {
+        ASSERT_GUEST_MSG_RETURN(paParms[i].type == VBOX_HGCM_SVC_PARM_32BIT, ("#%u type=%u\n", i, paParms[i].type),
+                                VERR_WRONG_PARAMETER_TYPE);
+        paParms[i].u.uint32 = 0;
+    }
+
+    /*
+     * Check restore session ID.
+     */
+    if (idRestoreCheck != 0)
+    {
+        uint64_t idRestore = g_pHelpers->pfnGetVMMDevSessionId(g_pHelpers);
+        if (idRestoreCheck != idRestore)
+        {
+            paParms[0].u.uint64 = idRestore;
+            LogFlowFunc(("[Client %RU32] VBOX_SHARED_CLIPBOARD_GUEST_FN_MSG_PEEK_XXX -> VERR_VM_RESTORED (%#RX64 -> %#RX64)\n",
+                         pClient->uClientID, idRestoreCheck, idRestore));
+            return VERR_VM_RESTORED;
+        }
+        Assert(!g_pHelpers->pfnIsCallRestored(hCall));
+    }
+
+    /*
+     * Return information about the first message if one is pending in the list.
+     */
+    if (!pClient->pData->queueMsg.isEmpty())
+    {
+        PVBOXCLIPBOARDCLIENTMSG pFirstMsg = pClient->pData->queueMsg.first();
+        if (pFirstMsg)
+        {
+            vboxSvcClipboardMsgSetPeekReturn(pFirstMsg, paParms, cParms);
+            LogFlowFunc(("[Client %RU32] VBOX_SHARED_CLIPBOARD_GUEST_FN_MSG_PEEK_XXX -> VINF_SUCCESS (idMsg=%u (%s), cParms=%u)\n",
+                         pClient->uClientID, pFirstMsg->m_uMsg, VBoxSvcClipboardHostMsgToStr(pFirstMsg->m_uMsg),
+                         pFirstMsg->m_cParms));
+            return VINF_SUCCESS;
+        }
+    }
+
+    /*
+     * If we cannot wait, fail the call.
+     */
+    if (!fWait)
+    {
+        LogFlowFunc(("[Client %RU32] GUEST_MSG_PEEK_NOWAIT -> VERR_TRY_AGAIN\n", pClient->uClientID));
+        return VERR_TRY_AGAIN;
+    }
+
+    /*
+     * Wait for the host to queue a message for this client.
+     */
+    ASSERT_GUEST_MSG_RETURN(pClient->Pending.uType == 0, ("Already pending! (idClient=%RU32)\n",
+                                                           pClient->uClientID), VERR_RESOURCE_BUSY);
+    pClient->Pending.hHandle = hCall;
+    pClient->Pending.cParms  = cParms;
+    pClient->Pending.paParms = paParms;
+    pClient->Pending.uType   = VBOX_SHARED_CLIPBOARD_GUEST_FN_MSG_PEEK_WAIT;
+    LogFlowFunc(("[Client %RU32] Is now in pending mode...\n", pClient->uClientID));
+    return VINF_HGCM_ASYNC_EXECUTE;
+}
+
+/**
+ * Implements VBOX_SHARED_CLIPBOARD_GUEST_FN_MSG_GET.
+ *
+ * @returns VBox status code.
+ * @retval  VINF_SUCCESS if message retrieved and removed from the pending queue.
+ * @retval  VERR_TRY_AGAIN if no message pending.
+ * @retval  VERR_BUFFER_OVERFLOW if a parmeter buffer is too small.  The buffer
+ *          size was updated to reflect the required size, though this isn't yet
+ *          forwarded to the guest.  (The guest is better of using peek with
+ *          parameter count + 2 parameters to get the sizes.)
+ * @retval  VERR_MISMATCH if the incoming message ID does not match the pending.
+ * @retval  VINF_HGCM_ASYNC_EXECUTE if message was completed already.
+ *
+ * @param   pClient      The client state.
+ * @param   hCall        The client's call handle.
+ * @param   cParms       Number of parameters.
+ * @param   paParms      Array of parameters.
+ */
+int vboxSvcClipboardMsgGet(PVBOXCLIPBOARDCLIENT pClient, VBOXHGCMCALLHANDLE hCall, uint32_t cParms, VBOXHGCMSVCPARM paParms[])
+{
+    /*
+     * Validate the request.
+     */
+    uint32_t const idMsgExpected = cParms > 0 && paParms[0].type == VBOX_HGCM_SVC_PARM_32BIT ? paParms[0].u.uint32
+                                 : cParms > 0 && paParms[0].type == VBOX_HGCM_SVC_PARM_64BIT ? paParms[0].u.uint64
+                                 : UINT32_MAX;
+
+    /*
+     * 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:
+                {
+                    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;
+                }
+
+                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. */
+        }
+
+        LogFlowFunc(("[Client %RU32] Returning %Rrc\n", pClient->uClientID, rc));
+        return rc;
+    }
+
+    paParms[0].u.uint32 = 0;
+    paParms[1].u.uint32 = 0;
+    LogFlowFunc(("[Client %RU32] -> VERR_TRY_AGAIN\n", pClient->uClientID));
+    return VERR_TRY_AGAIN;
+}
+
+int vboxSvcClipboardClientWakeup(PVBOXCLIPBOARDCLIENT pClient)
+{
+    int rc = VINF_NO_CHANGE;
+
+    if (pClient->Pending.uType)
+    {
+        LogFlowFunc(("[Client %RU32] Waking up ...\n", pClient->uClientID));
 
         rc = VINF_SUCCESS;
-    }
-
-    LogFlowFunc(("Returning puMsg=%RU32, pcParms=%RU32, rc=%Rrc\n", *puType, *pcParms, rc));
-    return rc;
-}
-
-/**
- * Retrieves the next queued up message and removes it from the queue on success.
- * Will return VERR_NO_DATA if no next message is available.
- *
- * @returns IPRT status code.
- * @param   pClientData         Pointer to the client data structure to get message for.
- * @param   uMsg                Message type to retrieve.
- * @param   cParms              Number of parameters the \@a paParms array can store.
- * @param   paParms             Where to store the message parameters.
- */
-int vboxSvcClipboardMsgGetNext(PVBOXCLIPBOARDCLIENTDATA pClientData,
-                               uint32_t uMsg, uint32_t cParms, VBOXHGCMSVCPARM paParms[])
-{
-    LogFlowFunc(("uMsg=%RU32, cParms=%RU32\n", uMsg, cParms));
-
-    /* Check for pending messages in our queue. */
-    if (pClientData->queueMsg.isEmpty())
-        return VERR_NO_DATA;
-
-    /* Get the current message. */
-    PVBOXCLIPBOARDCLIENTMSG pMsg = pClientData->queueMsg.first();
-    AssertPtr(pMsg);
-
-    int rc = VINF_SUCCESS;
-
-    /* Fetch the current message info. */
-    if (pMsg->m_uMsg != uMsg)
-    {
-        LogFunc(("Stored message type (%RU32) does not match request (%RU32)\n", pMsg->m_uMsg, uMsg));
-        rc = VERR_INVALID_PARAMETER;
-    }
-    else if (pMsg->m_cParms > cParms)
-    {
-        LogFunc(("Stored parameter count (%RU32) exceeds request buffer (%RU32)\n", pMsg->m_cParms, cParms));
-        rc = VERR_INVALID_PARAMETER;
-    }
-
-    if (RT_SUCCESS(rc))
-    {
-        rc = Message::CopyParms(paParms, cParms, pMsg->m_paParms, pMsg->m_cParms, true /* fDeepCopy */);
-
-        /** @todo Only remove on success? */
-        pClientData->queueMsg.removeFirst(); /* Remove the current message from the queue. */
-    }
-    else
-    {
-        vboxSvcClipboardMsgQueueReset(pClientData);
-        /** @todo Cleanup, send notification to guest. */
-    }
-
-    LogFlowFunc(("Message processed with rc=%Rrc\n", rc));
-    return rc;
+
+        if (!pClient->pData->queueMsg.isEmpty())
+        {
+            PVBOXCLIPBOARDCLIENTMSG pFirstMsg = pClient->pData->queueMsg.first();
+            if (pFirstMsg)
+            {
+                LogFlowFunc(("[Client %RU32] Current host message is %RU32 (cParms=%RU32)\n",
+                             pClient->uClientID, pFirstMsg->m_uMsg, pFirstMsg->m_cParms));
+
+                if (pClient->Pending.uType == VBOX_SHARED_CLIPBOARD_GUEST_FN_MSG_PEEK_WAIT)
+                {
+                    vboxSvcClipboardMsgSetPeekReturn(pFirstMsg, pClient->Pending.paParms, pClient->Pending.cParms);
+                    rc = g_pHelpers->pfnCallComplete(pClient->Pending.hHandle, VINF_SUCCESS);
+
+                    pClient->Pending.hHandle = NULL;
+                    pClient->Pending.paParms = NULL;
+                    pClient->Pending.cParms  = 0;
+                    pClient->Pending.uType   = false;
+                }
+            }
+            else
+                AssertFailed();
+        }
+        else
+            AssertMsgFailed(("Waking up client ID=%RU32 with no host message in queue is a bad idea\n", pClient->uClientID));
+
+        return rc;
+    }
+
+    return VINF_NO_CHANGE;
 }
 
@@ -919,5 +1120,5 @@
                                         SharedClipboardURITransferSetCallbacks(pTransfer, &Callbacks);
 
-                                        rc = SharedClipboardURITransferProviderCreate(pTransfer, &creationCtx);
+                                        rc = SharedClipboardURITransferSetInterface(pTransfer, &creationCtx);
                                         if (RT_SUCCESS(rc))
                                             rc = SharedClipboardURICtxTransferAdd(&pClientData->URI, pTransfer);
@@ -1036,5 +1237,5 @@
                                     creationCtx.pvUser = pClientData;
 
-                                    rc = SharedClipboardURITransferProviderCreate(pTransfer, &creationCtx);
+                                    rc = SharedClipboardURITransferSetInterface(pTransfer, &creationCtx);
                                     if (RT_SUCCESS(rc))
                                         rc = SharedClipboardURICtxTransferAdd(&pClientData->URI, pTransfer);
@@ -1233,114 +1434,4 @@
 
 /**
- * Defers a client from returning back to the caller (guest side).
- *
- * @returns VBox status code.
- * @param   pClient             Client to defer.
- * @param   hHandle             The call handle to defer.
- * @param   u32Function         Function ID to save.
- * @param   cParms              Number of parameters to save.
- * @param   paParms             Parameter arrray to save.
- */
-int vboxSvcClipboardClientDefer(PVBOXCLIPBOARDCLIENT pClient,
-                                VBOXHGCMCALLHANDLE hHandle, uint32_t u32Function, uint32_t cParms, VBOXHGCMSVCPARM paParms[])
-{
-    LogFlowFunc(("uClient=%RU32\n", pClient->uClientID));
-
-    AssertMsgReturn(pClient->fDeferred == false, ("Client already in deferred mode\n"),
-                    VERR_WRONG_ORDER);
-
-    pClient->fDeferred = true;
-
-    pClient->Deferred.hHandle = hHandle;
-    pClient->Deferred.uType   = u32Function;
-    pClient->Deferred.cParms  = cParms;
-    pClient->Deferred.paParms = paParms;
-
-    return false;
-}
-
-/**
- * Completes a call of a client, which in turn will return the result to the caller on
- * the guest side.
- *
- * @returns VBox status code.
- * @param   pClient             Client to complete.
- * @param   hHandle             Call handle to complete.
- * @param   rc                  Return code to set for the client.
- */
-int vboxSvcClipboardClientComplete(PVBOXCLIPBOARDCLIENT pClient, VBOXHGCMCALLHANDLE hHandle, int rc)
-{
-    RT_NOREF(pClient);
-
-    LogFlowFunc(("uClient=%RU32, rc=%Rrc\n", pClient->uClientID, rc));
-
-    g_pHelpers->pfnCallComplete(hHandle, rc);
-
-    return VINF_SUCCESS;
-}
-
-/**
- * Completes a deferred client.
- *
- * @returns VBox status code.
- * @param   pClient             Client to complete.
- * @param   rcComplete          Return code to set for the client.
- */
-int vboxSvcClipboardClientDeferredComplete(PVBOXCLIPBOARDCLIENT pClient, int rcComplete)
-{
-    LogFlowFunc(("uClient=%RU32, fDeferred=%RTbool\n", pClient->uClientID, pClient->fDeferred));
-
-    int rc = VINF_SUCCESS;
-
-    if (pClient->fDeferred) /* Not deferred? Bail out early. */
-    {
-        LogFlowFunc(("Completing call\n"));
-
-        rc = vboxSvcClipboardClientComplete(pClient, pClient->Deferred.hHandle, rcComplete);
-
-        pClient->fDeferred = false;
-        RT_ZERO(pClient->Deferred);
-    }
-
-    return rc;
-}
-
-/**
- * Sets a deferred client's next message info -- when returning to the client, it then
- * can retrieve the actual message sent by the host.
- *
- * @returns VBox status code.
- * @param   pClient             Client to set the next message information for.
- * @param   uMsg                Message ID to set.
- * @param   cParms              Number of parameters of message required.
- */
-int vboxSvcClipboardClientDeferredSetMsgInfo(PVBOXCLIPBOARDCLIENT pClient, uint32_t uMsg, uint32_t cParms)
-{
-    int rc;
-
-    LogFlowFunc(("uClient=%RU32\n", pClient->uClientID));
-
-    if (pClient->fDeferred)
-    {
-        if (pClient->Deferred.cParms >= 2)
-        {
-            AssertPtrReturn(pClient->Deferred.paParms, VERR_BUFFER_OVERFLOW);
-
-            HGCMSvcSetU32(&pClient->Deferred.paParms[0], uMsg);
-            HGCMSvcSetU32(&pClient->Deferred.paParms[1], cParms);
-
-            rc = VINF_SUCCESS;
-        }
-        else
-            rc = VERR_INVALID_PARAMETER;
-    }
-    else
-        rc = VERR_INVALID_STATE;
-
-    LogFlowFuncLeaveRC(rc);
-    return rc;
-}
-
-/**
  * Initializes a Shared Clipboard service's client state.
  *
