Index: trunk/include/VBox/GuestHost/SharedClipboard-transfers.h
===================================================================
--- trunk/include/VBox/GuestHost/SharedClipboard-transfers.h	(revision 80904)
+++ trunk/include/VBox/GuestHost/SharedClipboard-transfers.h	(revision 80905)
@@ -48,18 +48,24 @@
  */
 
-/** No status set. */
-#define SHCLTRANSFERSTATUS_NONE           0
-/** The transfer has been announced but is not running yet. */
-#define SHCLTRANSFERSTATUS_READY          1
-/** The transfer is active and running. */
-#define SHCLTRANSFERSTATUS_STARTED        2
-/** The transfer has been stopped. */
-#define SHCLTRANSFERSTATUS_STOPPED        3
-/** The transfer has been canceled. */
-#define SHCLTRANSFERSTATUS_CANCELED       4
-/** The transfer has been killed. */
-#define SHCLTRANSFERSTATUS_KILLED         5
-/** The transfer ran into an unrecoverable error. */
-#define SHCLTRANSFERSTATUS_ERROR          6
+/**
+ * Defines the transfer status codes.
+ */
+typedef enum
+{
+    /** No status set. */
+    SHCLTRANSFERSTATUS_NONE = 0,
+    /** The transfer has been initialized but is not running yet. */
+    SHCLTRANSFERSTATUS_INITIALIZED,
+    /** The transfer is active and running. */
+    SHCLTRANSFERSTATUS_STARTED,
+    /** The transfer has been stopped. */
+    SHCLTRANSFERSTATUS_STOPPED,
+    /** The transfer has been canceled. */
+    SHCLTRANSFERSTATUS_CANCELED,
+    /** The transfer has been killed. */
+    SHCLTRANSFERSTATUS_KILLED,
+    /** The transfer ran into an unrecoverable error. */
+    SHCLTRANSFERSTATUS_ERROR
+} SHCLTRANSFERSTATUSENUM;
 
 /** Defines a transfer status. */
@@ -873,5 +879,5 @@
     SHCLPROVIDERFUNCMEMBER(TRANSFEROPEN, pfnTransferOpen)
     SHCLPROVIDERFUNCMEMBER(TRANSFERCLOSE, pfnTransferClose)
-    SHCLPROVIDERFUNCMEMBER(GETROOTS, pfnGetRoots)
+    SHCLPROVIDERFUNCMEMBER(GETROOTS, pfnRootsGet)
     SHCLPROVIDERFUNCMEMBER(LISTOPEN, pfnListOpen)
     SHCLPROVIDERFUNCMEMBER(LISTCLOSE, pfnListClose)
@@ -913,10 +919,6 @@
 } SHCLTRANSFERCALLBACKDATA, *PSHCLTRANSFERCALLBACKDATA;
 
-#define SHCLTRANSFERCALLBACKDECLVOID(a_Name) \
-    typedef DECLCALLBACK(void) RT_CONCAT(FNSHCLCALLBACK, a_Name)(PSHCLTRANSFERCALLBACKDATA pData); \
-    typedef RT_CONCAT(FNSHCLCALLBACK, a_Name) RT_CONCAT(*PFNSHCLCALLBACK, a_Name);
-
-#define SHCLTRANSFERCALLBACKDECL(a_Name, ...) \
-    typedef DECLCALLBACK(void) RT_CONCAT(FNSHCLCALLBACK, a_Name)(PSHCLTRANSFERCALLBACKDATA pData, __VA_ARGS__); \
+#define SHCLTRANSFERCALLBACKDECL(a_Ret, a_Name, ...) \
+    typedef DECLCALLBACK(a_Ret) RT_CONCAT(FNSHCLCALLBACK, a_Name)(PSHCLTRANSFERCALLBACKDATA pData, __VA_ARGS__); \
     typedef RT_CONCAT(FNSHCLCALLBACK, a_Name) RT_CONCAT(*PFNSHCLCALLBACK, a_Name);
 
@@ -924,11 +926,11 @@
     RT_CONCAT(PFNSHCLCALLBACK, a_Name) a_Member;
 
-SHCLTRANSFERCALLBACKDECLVOID(TRANSFERPREPARE)
-SHCLTRANSFERCALLBACKDECLVOID(TRANSFERSTARTED)
-SHCLTRANSFERCALLBACKDECLVOID(LISTHEADERCOMPLETE)
-SHCLTRANSFERCALLBACKDECLVOID(LISTENTRYCOMPLETE)
-SHCLTRANSFERCALLBACKDECL    (TRANSFERCOMPLETE, int rc)
-SHCLTRANSFERCALLBACKDECLVOID(TRANSFERCANCELED)
-SHCLTRANSFERCALLBACKDECL    (TRANSFERERROR, int rc)
+SHCLTRANSFERCALLBACKDECL(int,  TRANSFERINITIALIZE)
+SHCLTRANSFERCALLBACKDECL(int,  TRANSFERSTART)
+SHCLTRANSFERCALLBACKDECL(void, LISTHEADERCOMPLETE)
+SHCLTRANSFERCALLBACKDECL(void, LISTENTRYCOMPLETE)
+SHCLTRANSFERCALLBACKDECL(void, TRANSFERCOMPLETE, int rc)
+SHCLTRANSFERCALLBACKDECL(void, TRANSFERCANCELED)
+SHCLTRANSFERCALLBACKDECL(void, TRANSFERERROR, int rc)
 
 /**
@@ -938,10 +940,10 @@
 typedef struct _SHCLTRANSFERCALLBACKS
 {
-    /** Saved user pointer. */
+    /** Saved user pointer. Optional and can be NULL. */
     void *pvUser;
-    /** Function pointer, called when the transfer is going to be prepared. */
-    SHCLTRANSFERCALLBACKMEMBER(TRANSFERPREPARE, pfnTransferPrepare)
-    /** Function pointer, called when the transfer has been started. */
-    SHCLTRANSFERCALLBACKMEMBER(TRANSFERSTARTED, pfnTransferStarted)
+    /** Function pointer, called after the transfer has been initialized. */
+    SHCLTRANSFERCALLBACKMEMBER(TRANSFERINITIALIZE, pfnTransferInitialize)
+    /** Function pointer, called before the transfer will be started. */
+    SHCLTRANSFERCALLBACKMEMBER(TRANSFERSTART, pfnTransferStart)
     /** Function pointer, called when reading / writing the list header is complete. */
     SHCLTRANSFERCALLBACKMEMBER(LISTHEADERCOMPLETE, pfnListHeaderComplete)
@@ -1079,21 +1081,14 @@
 int SharedClipboardTransferClose(PSHCLTRANSFER pTransfer);
 
-int SharedClipboardTransferListOpen(PSHCLTRANSFER pTransfer, PSHCLLISTOPENPARMS pOpenParms,
-                                       PSHCLLISTHANDLE phList);
+int SharedClipboardTransferListOpen(PSHCLTRANSFER pTransfer, PSHCLLISTOPENPARMS pOpenParms, PSHCLLISTHANDLE phList);
 int SharedClipboardTransferListClose(PSHCLTRANSFER pTransfer, SHCLLISTHANDLE hList);
-int SharedClipboardTransferListGetHeader(PSHCLTRANSFER pTransfer, SHCLLISTHANDLE hList,
-                                            PSHCLLISTHDR pHdr);
-PSHCLTRANSFEROBJ SharedClipboardTransferListGetObj(PSHCLTRANSFER pTransfer,
-                                                                    SHCLLISTHANDLE hList, uint64_t uIdx);
-int SharedClipboardTransferListRead(PSHCLTRANSFER pTransfer, SHCLLISTHANDLE hList,
-                                       PSHCLLISTENTRY pEntry);
-int SharedClipboardTransferListWrite(PSHCLTRANSFER pTransfer, SHCLLISTHANDLE hList,
-                                        PSHCLLISTENTRY pEntry);
+int SharedClipboardTransferListGetHeader(PSHCLTRANSFER pTransfer, SHCLLISTHANDLE hList, PSHCLLISTHDR pHdr);
+PSHCLTRANSFEROBJ SharedClipboardTransferListGetObj(PSHCLTRANSFER pTransfer, SHCLLISTHANDLE hList, uint64_t uIdx);
+int SharedClipboardTransferListRead(PSHCLTRANSFER pTransfer, SHCLLISTHANDLE hList, PSHCLLISTENTRY pEntry);
+int SharedClipboardTransferListWrite(PSHCLTRANSFER pTransfer, SHCLLISTHANDLE hList, PSHCLLISTENTRY pEntry);
 bool SharedClipboardTransferListHandleIsValid(PSHCLTRANSFER pTransfer, SHCLLISTHANDLE hList);
 
-int SharedClipboardTransferPrepare(PSHCLTRANSFER pTransfer);
-int SharedClipboardTransferSetInterface(PSHCLTRANSFER pTransfer,
-                                           PSHCLPROVIDERCREATIONCTX pCreationCtx);
-int SharedClipboardTransferSetRoots(PSHCLTRANSFER pTransfer, const char *pszRoots, size_t cbRoots);
+int SharedClipboardTransferSetInterface(PSHCLTRANSFER pTransfer, PSHCLPROVIDERCREATIONCTX pCreationCtx);
+int SharedClipboardTransferRootsSet(PSHCLTRANSFER pTransfer, const char *pszRoots, size_t cbRoots);
 void SharedClipboardTransferReset(PSHCLTRANSFER pTransfer);
 SharedClipboardArea *SharedClipboardTransferGetArea(PSHCLTRANSFER pTransfer);
@@ -1101,5 +1096,5 @@
 uint32_t SharedClipboardTransferRootsCount(PSHCLTRANSFER pTransfer);
 int SharedClipboardTransferRootsEntry(PSHCLTRANSFER pTransfer, uint64_t uIndex, PSHCLROOTLISTENTRY pEntry);
-int SharedClipboardTransferRootsAsList(PSHCLTRANSFER pTransfer, PSHCLROOTLIST *ppRootList);
+int SharedClipboardTransferRootsGet(PSHCLTRANSFER pTransfer, PSHCLROOTLIST *ppRootList);
 
 SHCLTRANSFERID SharedClipboardTransferGetID(PSHCLTRANSFER pTransfer);
@@ -1108,4 +1103,5 @@
 int SharedClipboardTransferHandleReply(PSHCLTRANSFER pTransfer, PSHCLREPLY pReply);
 int SharedClipboardTransferRun(PSHCLTRANSFER pTransfer, PFNRTTHREAD pfnThreadFunc, void *pvUser);
+int SharedClipboardTransferStart(PSHCLTRANSFER pTransfer);
 void SharedClipboardTransferSetCallbacks(PSHCLTRANSFER pTransfer, PSHCLTRANSFERCALLBACKS pCallbacks);
 
@@ -1133,5 +1129,5 @@
 bool SharedClipboardMIMENeedsCache(const char *pcszFormat, size_t cchFormatMax);
 
-const char *VBoxShClTransferStatusToStr(uint32_t uStatus);
+const char *VBoxShClTransferStatusToStr(SHCLTRANSFERSTATUS enmStatus);
 
 #endif /* !VBOX_INCLUDED_GuestHost_SharedClipboard_transfers_h */
Index: trunk/include/VBox/VBoxGuestLib.h
===================================================================
--- trunk/include/VBox/VBoxGuestLib.h	(revision 80904)
+++ trunk/include/VBox/VBoxGuestLib.h	(revision 80905)
@@ -576,4 +576,15 @@
  * @{ */
 
+#  ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
+/**
+ * Structure containing context parameters for Shared Clipboard transfers.
+ */
+typedef struct VBGLR3SHCLTRANSFERCMDCTX
+{
+    /** Callback table to use for all transfers. */
+    SHCLTRANSFERCALLBACKS Callbacks;
+} VBGLR3SHCLTRANSFERCMDCTX, *PVBGLR3SHCLTRANSFERCMDCTX;
+#  endif /* VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS */
+
 /**
  * Structure containing the context required for
@@ -591,15 +602,18 @@
 
     /** IN: HGCM client ID to use for communication. */
-    uint32_t            uClientID;
+    uint32_t                  uClientID;
     /** IN/OUT: Context ID to retrieve or to use. */
-    uint32_t            uContextID;
+    uint32_t                  uContextID;
     /** IN: Protocol version to use. */
-    uint32_t            uProtocolVer;
+    uint32_t                  uProtocolVer;
     /** IN: Protocol flags. Currently unused. */
-    uint32_t            uProtocolFlags;
+    uint32_t                  uProtocolFlags;
     /** IN: Maximum chunk size (in bytes). */
-    uint32_t            cbChunkSize;
+    uint32_t                  cbChunkSize;
     /** OUT: Number of parameters retrieved. */
-    uint32_t            uNumParms;
+    uint32_t                  uNumParms;
+#  ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
+    VBGLR3SHCLTRANSFERCMDCTX  Transfers;
+#  endif
 } VBGLR3SHCLCMDCTX, *PVBGLR3SHCLCMDCTX;
 
@@ -613,8 +627,8 @@
     VBGLR3CLIPBOARDEVENTTYPE_READ_DATA,
     VBGLR3CLIPBOARDEVENTTYPE_QUIT,
-#ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
+#  ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
     /** Reports a transfer status to the guest. */
     VBGLR3CLIPBOARDEVENTTYPE_URI_TRANSFER_STATUS,
-#endif
+#  endif
     /** Blow the type up to 32-bit. */
     VBGLR3CLIPBOARDEVENTTYPE_32BIT_HACK = 0x7fffffff
@@ -636,5 +650,5 @@
         /** Reports that data needs to be read from the guest. */
         SHCLDATAREQ          ReadData;
-#ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
+#  ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
         /** Reports a transfer status to the guest. */
         struct
@@ -647,5 +661,5 @@
             SHCLTRANSFERREPORT Report;
         } TransferStatus;
-#endif
+#  endif /* VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS */
     } u;
 } VBGLR3CLIPBOARDEVENT, *PVBGLR3CLIPBOARDEVENT;
Index: trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxClipboard.cpp
===================================================================
--- trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxClipboard.cpp	(revision 80904)
+++ trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxClipboard.cpp	(revision 80905)
@@ -94,6 +94,7 @@
 *********************************************************************************************************************************/
 #ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
-static DECLCALLBACK(void) vboxClipboardTransferCompleteCallback(PSHCLTRANSFERCALLBACKDATA pData, int rc);
-static DECLCALLBACK(void) vboxClipboardTransferErrorCallback(PSHCLTRANSFERCALLBACKDATA pData, int rc);
+static DECLCALLBACK(int)  vboxClipboardOnTransferStartCallback(PSHCLTRANSFERCALLBACKDATA pData);
+static DECLCALLBACK(void) vboxClipboardOnTransferCompleteCallback(PSHCLTRANSFERCALLBACKDATA pData, int rc);
+static DECLCALLBACK(void) vboxClipboardOnTransferErrorCallback(PSHCLTRANSFERCALLBACKDATA pData, int rc);
 #endif
 
@@ -183,9 +184,64 @@
 }
 
-static DECLCALLBACK(void) vboxClipboardTransferCompleteCallback(PSHCLTRANSFERCALLBACKDATA pData, int rc)
-{
-    RT_NOREF(rc);
-
-    LogFlowFunc(("pData=%p, rc=%Rrc\n", pData, rc));
+static DECLCALLBACK(int) vboxClipboardOnTransferStartCallback(PSHCLTRANSFERCALLBACKDATA pData)
+{
+    PSHCLCONTEXT pCtx = (PSHCLCONTEXT)pData->pvUser;
+    AssertPtr(pCtx);
+
+    LogFlowFunc(("pCtx=%p\n", pCtx));
+
+    int rc = SharedClipboardWinOpen(pCtx->Win.hWnd);
+    if (RT_SUCCESS(rc))
+    {
+        PSHCLTRANSFER pTransfer;
+        rc = SharedClipboardTransferCreate(&pTransfer);
+        if (RT_SUCCESS(rc))
+            rc = SharedClipboardTransferInit(pTransfer, 0 /* uID */,
+                                             SHCLTRANSFERDIR_WRITE, SHCLSOURCE_LOCAL);
+        if (RT_SUCCESS(rc))
+        {
+            /* The data data in CF_HDROP format, as the files are locally present and don't need to be
+             * presented as a IDataObject or IStream. */
+            HANDLE hClip = hClip = GetClipboardData(CF_HDROP);
+            if (hClip)
+            {
+                HDROP hDrop = (HDROP)GlobalLock(hClip);
+                if (hDrop)
+                {
+                    char    *papszList = NULL;
+                    uint32_t cbList;
+                    rc = SharedClipboardWinDropFilesToStringList((DROPFILES *)hDrop, &papszList, &cbList);
+
+                    GlobalUnlock(hClip);
+
+                    if (RT_SUCCESS(rc))
+                    {
+                        rc = SharedClipboardTransferRootsSet(pTransfer,
+                                                             papszList, cbList + 1 /* Include termination */);
+                        RTStrFree(papszList);
+                    }
+                }
+                else
+                {
+                    hClip = NULL;
+                }
+            }
+        }
+
+        SharedClipboardWinClose();
+    }
+
+    LogFlowFuncLeaveRC(rc);
+    return rc;
+}
+
+static DECLCALLBACK(void) vboxClipboardOnTransferCompleteCallback(PSHCLTRANSFERCALLBACKDATA pData, int rc)
+{
+    PSHCLCONTEXT pCtx = (PSHCLCONTEXT)pData->pvUser;
+    AssertPtr(pCtx);
+
+    RT_NOREF(pCtx, rc);
+
+    LogFlowFunc(("pCtx=%p, rc=%Rrc\n", pCtx, rc));
 
     LogRel2(("Shared Clipboard: Transfer to destination complete\n"));
@@ -194,9 +250,12 @@
 }
 
-static DECLCALLBACK(void) vboxClipboardTransferErrorCallback(PSHCLTRANSFERCALLBACKDATA pData, int rc)
-{
-    RT_NOREF(rc);
-
-    LogFlowFunc(("pData=%p, rc=%Rrc\n", pData, rc));
+static DECLCALLBACK(void) vboxClipboardOnTransferErrorCallback(PSHCLTRANSFERCALLBACKDATA pData, int rc)
+{
+    PSHCLCONTEXT pCtx = (PSHCLCONTEXT)pData->pvUser;
+    AssertPtr(pCtx);
+
+    RT_NOREF(pCtx, rc);
+
+    LogFlowFunc(("pCtx=%p, rc=%Rrc\n", pCtx, rc));
 
     LogRel(("Shared Clipboard: Transfer to destination failed with %Rrc\n", rc));
@@ -770,5 +829,5 @@
                    }
                }
-#ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
+#if 0
                else if (uFormat == VBOX_SHCL_FMT_URI_LIST)
                {
@@ -979,5 +1038,5 @@
                creationCtx.enmSource = SHCLSOURCE_REMOTE;
 
-               creationCtx.Interface.pfnGetRoots      = vboxClipboardTransferGetRoots;
+               creationCtx.Interface.pfnRootsGet      = vboxClipboardTransferGetRoots;
                creationCtx.Interface.pfnListOpen      = vboxClipboardTransferListOpen;
                creationCtx.Interface.pfnListClose     = vboxClipboardTransferListClose;
@@ -1151,5 +1210,16 @@
     }
     else
+    {
         LogRel(("Shared Clipboard: Initialized OLE\n"));
+
+        /* Install callbacks. */
+        RT_ZERO(pCtx->CmdCtx.Transfers.Callbacks);
+
+        pCtx->CmdCtx.Transfers.Callbacks.pvUser = pCtx; /* Assign context as user-provided callback data. */
+
+        pCtx->CmdCtx.Transfers.Callbacks.pfnTransferStart    = vboxClipboardOnTransferStartCallback;
+        pCtx->CmdCtx.Transfers.Callbacks.pfnTransferComplete = vboxClipboardOnTransferCompleteCallback;
+        pCtx->CmdCtx.Transfers.Callbacks.pfnTransferError    = vboxClipboardOnTransferErrorCallback;
+    }
 #endif
 
Index: trunk/src/VBox/Additions/common/VBoxGuest/lib/VBoxGuestR3LibClipboard.cpp
===================================================================
--- trunk/src/VBox/Additions/common/VBoxGuest/lib/VBoxGuestR3LibClipboard.cpp	(revision 80904)
+++ trunk/src/VBox/Additions/common/VBoxGuest/lib/VBoxGuestR3LibClipboard.cpp	(revision 80905)
@@ -1263,9 +1263,15 @@
     if (RT_SUCCESS(rc))
     {
+        SharedClipboardTransferSetCallbacks(pTransfer, &pCmdCtx->Transfers.Callbacks);
+
         rc = SharedClipboardTransferCtxTransferRegisterByIndex(pTransferCtx, pTransfer, uTransferID);
         if (RT_SUCCESS(rc))
         {
             rc = SharedClipboardTransferInit(pTransfer, uTransferID, enmDir, enmSource);
-            if (RT_FAILURE(rc))
+            if (RT_SUCCESS(rc))
+            {
+                rc = SharedClipboardTransferStart(pTransfer);
+            }
+            else
                 SharedClipboardTransferCtxTransferUnregister(pTransferCtx, uTransferID);
         }
@@ -1359,5 +1365,5 @@
                 switch (transferReport.uStatus)
                 {
-                    case SHCLTRANSFERSTATUS_READY:
+                    case SHCLTRANSFERSTATUS_INITIALIZED:
                         RT_FALL_THROUGH();
                     case SHCLTRANSFERSTATUS_STARTED:
Index: trunk/src/VBox/GuestHost/SharedClipboard/ClipboardDataObjectImpl-win.cpp
===================================================================
--- trunk/src/VBox/GuestHost/SharedClipboard/ClipboardDataObjectImpl-win.cpp	(revision 80904)
+++ trunk/src/VBox/GuestHost/SharedClipboard/ClipboardDataObjectImpl-win.cpp	(revision 80905)
@@ -335,5 +335,5 @@
     {
         PSHCLROOTLIST pRootList;
-        rc = SharedClipboardTransferLTransferRootsAsList(pTransfer, &pRootList);
+        rc = SharedClipboardTransferRootsGet(pTransfer, &pRootList);
         if (RT_SUCCESS(rc))
         {
@@ -570,25 +570,24 @@
         const bool fUnicode = pFormatEtc->cfFormat == m_cfFileDescriptorW;
 
-        LogFlowFunc(("FormatIndex_FileDescriptor%s\n", fUnicode ? "W" : "A"));
+        const uint32_t enmTransferStatus = SharedClipboardTransferGetStatus(m_pTransfer);
+
+        LogFlowFunc(("FormatIndex_FileDescriptor%s, transfer status is %s\n",
+                     fUnicode ? "W" : "A", VBoxShClTransferStatusToStr(enmTransferStatus)));
 
         int rc;
 
         /* The caller can call GetData() several times, so make sure we don't do the same transfer multiple times. */
-        if (SharedClipboardTransferGetStatus(m_pTransfer) == SHCLTRANSFERSTATUS_NONE)
-        {
-            rc = SharedClipboardTransferPrepare(m_pTransfer);
+        if (enmTransferStatus == SHCLTRANSFERSTATUS_INITIALIZED)
+        {
+            /* Start the transfer asynchronously in a separate thread. */
+            rc = SharedClipboardTransferRun(m_pTransfer, &SharedClipboardWinDataObject::readThread, this);
             if (RT_SUCCESS(rc))
             {
-                /* Start the transfer asynchronously in a separate thread. */
-                rc = SharedClipboardTransferRun(m_pTransfer, &SharedClipboardWinDataObject::readThread, this);
+                /* 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, 30 * 1000 /* 30s timeout */);
                 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, 30 * 1000 /* 30s timeout */);
-                    if (RT_SUCCESS(rc))
-                    {
-                        LogFunc(("Listing complete\n"));
-                    }
+                    LogFunc(("Listing complete\n"));
                 }
             }
Index: trunk/src/VBox/GuestHost/SharedClipboard/clipboard-transfers.cpp
===================================================================
--- trunk/src/VBox/GuestHost/SharedClipboard/clipboard-transfers.cpp	(revision 80904)
+++ trunk/src/VBox/GuestHost/SharedClipboard/clipboard-transfers.cpp	(revision 80905)
@@ -1157,5 +1157,5 @@
 
 /**
- * Initializes an Shared Clipboard transfer object.
+ * Initializes a shared Clipboard transfer object.
  *
  * @returns VBox status code.
@@ -1173,4 +1173,14 @@
 
     int rc = SharedClipboardEventSourceCreate(&pTransfer->Events, pTransfer->State.uID);
+    if (RT_SUCCESS(rc))
+    {
+        pTransfer->State.enmStatus = SHCLTRANSFERSTATUS_INITIALIZED; /* Now we're ready to run. */
+
+        if (pTransfer->Callbacks.pfnTransferInitialize)
+        {
+            SHCLTRANSFERCALLBACKDATA Data = { pTransfer, pTransfer->Callbacks.pvUser };
+            rc = pTransfer->Callbacks.pfnTransferInitialize(&Data);
+        }
+    }
 
     LogFlowFuncLeaveRC(rc);
@@ -1644,5 +1654,5 @@
 
 /**
- * Returns the current transfer object for a clipboard Shared Clipboard transfer list.
+ * Returns the current transfer object for a Shared Clipboard transfer list.
  *
  * Currently not implemented and wil return NULL.
@@ -1853,40 +1863,4 @@
 
 /**
- * Prepares everything needed for a read / write transfer to begin.
- *
- * @returns VBox status code.
- * @param   pTransfer           Clipboard transfer to prepare.
- */
-int SharedClipboardTransferPrepare(PSHCLTRANSFER pTransfer)
-{
-    AssertPtrReturn(pTransfer, VERR_INVALID_POINTER);
-
-    LogFlowFuncEnter();
-
-    int rc = VINF_SUCCESS;
-
-    AssertMsgReturn(pTransfer->State.enmStatus == SHCLTRANSFERSTATUS_NONE,
-                    ("Transfer has wrong state (%RU32)\n", pTransfer->State.enmStatus), VERR_WRONG_ORDER);
-
-    LogFlowFunc(("pTransfer=%p, enmDir=%RU32\n", pTransfer, pTransfer->State.enmDir));
-
-    if (pTransfer->Callbacks.pfnTransferPrepare)
-    {
-        SHCLTRANSFERCALLBACKDATA callbackData = { pTransfer, pTransfer->Callbacks.pvUser };
-        pTransfer->Callbacks.pfnTransferPrepare(&callbackData);
-    }
-
-    if (RT_SUCCESS(rc))
-    {
-        pTransfer->State.enmStatus = SHCLTRANSFERSTATUS_READY;
-
-        /** @todo Add checksum support. */
-    }
-
-    LogFlowFuncLeaveRC(rc);
-    return rc;
-}
-
-/**
  * Sets the transfer provider interface for a given transfer.
  *
@@ -1913,5 +1887,5 @@
     LOG_IFACE_PTR(pfnTransferOpen);
     LOG_IFACE_PTR(pfnTransferClose);
-    LOG_IFACE_PTR(pfnGetRoots);
+    LOG_IFACE_PTR(pfnRootsGet);
     LOG_IFACE_PTR(pfnListOpen);
     LOG_IFACE_PTR(pfnListClose);
@@ -1928,5 +1902,5 @@
 
 /**
- * Clears (resets) the root list of an Shared Clipboard transfer.
+ * Clears (resets) the root list of a shared Clipboard transfer.
  *
  * @param   pTransfer           Transfer to clear transfer root list for.
@@ -1957,91 +1931,19 @@
 
 /**
- * Sets transfer root list entries for a given transfer.
- *
- * @returns VBox status code.
- * @param   pTransfer           Transfer to set transfer list entries for.
- * @param   pszRoots            String list (separated by CRLF) of root entries to set.
- *                              All entries must have the same root path.
- * @param   cbRoots             Size (in bytes) of string list.
- */
-int SharedClipboardTransferSetRoots(PSHCLTRANSFER pTransfer, const char *pszRoots, size_t cbRoots)
-{
-    AssertPtrReturn(pTransfer,      VERR_INVALID_POINTER);
-    AssertPtrReturn(pszRoots,       VERR_INVALID_POINTER);
-    AssertReturn(cbRoots,           VERR_INVALID_PARAMETER);
-
-    if (!RTStrIsValidEncoding(pszRoots))
-        return VERR_INVALID_PARAMETER;
-
-    int rc = VINF_SUCCESS;
+ * Resets a shared Clipboard transfer.
+ *
+ * @param   pTransfer           Clipboard transfer to reset.
+ */
+void SharedClipboardTransferReset(PSHCLTRANSFER pTransfer)
+{
+    AssertPtrReturnVoid(pTransfer);
+
+    LogFlowFuncEnter();
 
     sharedClipboardTransferListRootsClear(pTransfer);
-
-    char  *pszPathRootAbs = NULL;
-
-    RTCList<RTCString> lstRootEntries = RTCString(pszRoots, cbRoots - 1).split("\r\n");
-    for (size_t i = 0; i < lstRootEntries.size(); ++i)
-    {
-        PSHCLLISTROOT pListRoot = (PSHCLLISTROOT)RTMemAlloc(sizeof(SHCLLISTROOT));
-        AssertPtrBreakStmt(pListRoot, rc = VERR_NO_MEMORY);
-
-        pListRoot->pszPathAbs = RTStrDup(lstRootEntries.at(i).c_str());
-        AssertPtrBreakStmt(pListRoot->pszPathAbs, rc = VERR_NO_MEMORY);
-
-        if (!pszPathRootAbs)
-        {
-            pszPathRootAbs = RTStrDup(pListRoot->pszPathAbs);
-            if (pszPathRootAbs)
-            {
-                RTPathStripFilename(pszPathRootAbs);
-                LogFlowFunc(("pszPathRootAbs=%s\n", pszPathRootAbs));
-            }
-            else
-                rc = VERR_NO_MEMORY;
-        }
-
-        if (RT_FAILURE(rc))
-            break;
-
-        /* Make sure all entries have the same root path. */
-        if (!RTStrStartsWith(pListRoot->pszPathAbs, pszPathRootAbs))
-        {
-            rc = VERR_INVALID_PARAMETER;
-            break;
-        }
-
-        RTListAppend(&pTransfer->lstRoots, &pListRoot->Node);
-
-        pTransfer->cRoots++;
-    }
-
-    /** @todo Entry rollback on failure? */
-
-    if (RT_SUCCESS(rc))
-    {
-        pTransfer->pszPathRootAbs = pszPathRootAbs;
-        LogFlowFunc(("pszPathRootAbs=%s, cRoots=%zu\n", pTransfer->pszPathRootAbs, pTransfer->cRoots));
-    }
-
-    LogFlowFuncLeaveRC(rc);
-    return rc;
-}
-
-/**
- * Resets an clipboard Shared Clipboard transfer.
- *
- * @param   pTransfer           Clipboard transfer to reset.
- */
-void SharedClipboardTransferReset(PSHCLTRANSFER pTransfer)
-{
-    AssertPtrReturnVoid(pTransfer);
-
-    LogFlowFuncEnter();
-
-    sharedClipboardTransferListRootsClear(pTransfer);
-}
-
-/**
- * Returns the clipboard area for a clipboard Shared Clipboard transfer.
+}
+
+/**
+ * Returns the clipboard area for a Shared Clipboard transfer.
  *
  * @returns Current clipboard area, or NULL if none.
@@ -2075,5 +1977,5 @@
  * @param   uIdx                Index of root list entry to return.
  */
-inline PSHCLLISTROOT sharedClipboardTransferRootsGet(PSHCLTRANSFER pTransfer, uint32_t uIdx)
+inline PSHCLLISTROOT sharedClipboardTransferRootsGetInternal(PSHCLTRANSFER pTransfer, uint32_t uIdx)
 {
     if (uIdx >= pTransfer->cRoots)
@@ -2081,5 +1983,5 @@
 
     PSHCLLISTROOT pIt = RTListGetFirst(&pTransfer->lstRoots, SHCLLISTROOT, Node);
-    while (uIdx--)
+    while (uIdx--) /** @todo Slow, but works for now. */
         pIt = RTListGetNext(&pTransfer->lstRoots, pIt, SHCLLISTROOT, Node);
 
@@ -2096,5 +1998,5 @@
  */
 int SharedClipboardTransferRootsEntry(PSHCLTRANSFER pTransfer,
-                                               uint64_t uIndex, PSHCLROOTLISTENTRY pEntry)
+                                      uint64_t uIndex, PSHCLROOTLISTENTRY pEntry)
 {
     AssertPtrReturn(pTransfer, VERR_INVALID_POINTER);
@@ -2106,5 +2008,5 @@
     int rc;
 
-    PSHCLLISTROOT pRoot = sharedClipboardTransferRootsGet(pTransfer, uIndex);
+    PSHCLLISTROOT pRoot = sharedClipboardTransferRootsGetInternal(pTransfer, uIndex);
     AssertPtrReturn(pRoot, VERR_INVALID_PARAMETER);
 
@@ -2153,5 +2055,5 @@
 
 /**
- * Returns the root entries of an Shared Clipboard transfer.
+ * Returns the root entries of a shared Clipboard transfer.
  *
  * @returns VBox status code.
@@ -2159,5 +2061,5 @@
  * @param   ppRootList          Where to store the root list on success.
  */
-int SharedClipboardTransferRootsAsList(PSHCLTRANSFER pTransfer, PSHCLROOTLIST *ppRootList)
+int SharedClipboardTransferRootsGet(PSHCLTRANSFER pTransfer, PSHCLROOTLIST *ppRootList)
 {
     AssertPtrReturn(pTransfer,  VERR_INVALID_POINTER);
@@ -2210,6 +2112,6 @@
     else if (pTransfer->State.enmSource == SHCLSOURCE_REMOTE)
     {
-        if (pTransfer->ProviderIface.pfnGetRoots)
-            rc = pTransfer->ProviderIface.pfnGetRoots(&pTransfer->ProviderCtx, ppRootList);
+        if (pTransfer->ProviderIface.pfnRootsGet)
+            rc = pTransfer->ProviderIface.pfnRootsGet(&pTransfer->ProviderCtx, ppRootList);
         else
             rc = VERR_NOT_SUPPORTED;
@@ -2220,4 +2122,77 @@
 }
 
+
+/**
+ * Sets transfer root list entries for a given transfer.
+ *
+ * @returns VBox status code.
+ * @param   pTransfer           Transfer to set transfer list entries for.
+ * @param   pszRoots            String list (separated by CRLF) of root entries to set.
+ *                              All entries must have the same root path.
+ * @param   cbRoots             Size (in bytes) of string list.
+ */
+int SharedClipboardTransferRootsSet(PSHCLTRANSFER pTransfer, const char *pszRoots, size_t cbRoots)
+{
+    AssertPtrReturn(pTransfer,      VERR_INVALID_POINTER);
+    AssertPtrReturn(pszRoots,       VERR_INVALID_POINTER);
+    AssertReturn(cbRoots,           VERR_INVALID_PARAMETER);
+
+    if (!RTStrIsValidEncoding(pszRoots))
+        return VERR_INVALID_PARAMETER;
+
+    int rc = VINF_SUCCESS;
+
+    sharedClipboardTransferListRootsClear(pTransfer);
+
+    char  *pszPathRootAbs = NULL;
+
+    RTCList<RTCString> lstRootEntries = RTCString(pszRoots, cbRoots - 1).split("\r\n");
+    for (size_t i = 0; i < lstRootEntries.size(); ++i)
+    {
+        PSHCLLISTROOT pListRoot = (PSHCLLISTROOT)RTMemAlloc(sizeof(SHCLLISTROOT));
+        AssertPtrBreakStmt(pListRoot, rc = VERR_NO_MEMORY);
+
+        pListRoot->pszPathAbs = RTStrDup(lstRootEntries.at(i).c_str());
+        AssertPtrBreakStmt(pListRoot->pszPathAbs, rc = VERR_NO_MEMORY);
+
+        if (!pszPathRootAbs)
+        {
+            pszPathRootAbs = RTStrDup(pListRoot->pszPathAbs);
+            if (pszPathRootAbs)
+            {
+                RTPathStripFilename(pszPathRootAbs);
+                LogFlowFunc(("pszPathRootAbs=%s\n", pszPathRootAbs));
+            }
+            else
+                rc = VERR_NO_MEMORY;
+        }
+
+        if (RT_FAILURE(rc))
+            break;
+
+        /* Make sure all entries have the same root path. */
+        if (!RTStrStartsWith(pListRoot->pszPathAbs, pszPathRootAbs))
+        {
+            rc = VERR_INVALID_PARAMETER;
+            break;
+        }
+
+        RTListAppend(&pTransfer->lstRoots, &pListRoot->Node);
+
+        pTransfer->cRoots++;
+    }
+
+    /** @todo Entry rollback on failure? */
+
+    if (RT_SUCCESS(rc))
+    {
+        pTransfer->pszPathRootAbs = pszPathRootAbs;
+        LogFlowFunc(("pszPathRootAbs=%s, cRoots=%zu\n", pTransfer->pszPathRootAbs, pTransfer->cRoots));
+    }
+
+    LogFlowFuncLeaveRC(rc);
+    return rc;
+}
+
 /**
  * Returns the transfer's ID.
@@ -2260,5 +2235,5 @@
 
 /**
- * Runs (starts) an Shared Clipboard transfer thread.
+ * Starts (runs) a Shared Clipboard transfer in a dedicated thread.
  *
  * @returns VBox status code.
@@ -2271,8 +2246,7 @@
     AssertPtrReturn(pTransfer, VERR_INVALID_POINTER);
 
-    AssertMsgReturn(pTransfer->State.enmStatus == SHCLTRANSFERSTATUS_READY,
-                    ("Wrong status (currently is %RU32)\n", pTransfer->State.enmStatus), VERR_WRONG_ORDER);
-
-    int rc = sharedClipboardTransferThreadCreate(pTransfer, pfnThreadFunc, pvUser);
+    int rc = SharedClipboardTransferStart(pTransfer);
+    if (RT_SUCCESS(rc))
+        rc = sharedClipboardTransferThreadCreate(pTransfer, pfnThreadFunc, pvUser);
 
     LogFlowFuncLeaveRC(rc);
@@ -2281,5 +2255,36 @@
 
 /**
- * Sets or unsets the callback table to be used for a clipboard Shared Clipboard transfer.
+ * Starts an initialized transfer.
+ *
+ * @returns VBox status code.
+ * @param   pTransfer           Clipboard transfer to start.
+ */
+int SharedClipboardTransferStart(PSHCLTRANSFER pTransfer)
+{
+    AssertPtrReturn(pTransfer, VERR_INVALID_POINTER);
+
+    /* Ready to start? */
+    AssertMsgReturn(pTransfer->State.enmStatus == SHCLTRANSFERSTATUS_INITIALIZED,
+                    ("Wrong status (currently is %s)\n", VBoxShClTransferStatusToStr(pTransfer->State.enmStatus)),
+                    VERR_WRONG_ORDER);
+
+    int rc;
+
+    if (pTransfer->Callbacks.pfnTransferStart)
+    {
+        SHCLTRANSFERCALLBACKDATA Data = { pTransfer, pTransfer->Callbacks.pvUser };
+        rc = pTransfer->Callbacks.pfnTransferStart(&Data);
+    }
+    else
+        rc = VINF_SUCCESS;
+
+    /* Nothing else to do here right now. */
+
+    LogFlowFuncLeaveRC(rc);
+    return rc;
+}
+
+/**
+ * Sets or unsets the callback table to be used for a Shared Clipboard transfer.
  *
  * @returns VBox status code.
@@ -2299,11 +2304,10 @@
         pTransfer->Callbacks.a_pfnCallback = pCallbacks->a_pfnCallback
 
-    SET_CALLBACK(pfnTransferPrepare);
-    SET_CALLBACK(pfnTransferStarted);
+    SET_CALLBACK(pfnTransferInitialize);
+    SET_CALLBACK(pfnTransferStart);
     SET_CALLBACK(pfnListHeaderComplete);
     SET_CALLBACK(pfnListEntryComplete);
     SET_CALLBACK(pfnTransferCanceled);
     SET_CALLBACK(pfnTransferError);
-    SET_CALLBACK(pfnTransferStarted);
 
 #undef SET_CALLBACK
@@ -2313,5 +2317,5 @@
 
 /**
- * Creates a thread for a clipboard Shared Clipboard transfer.
+ * Creates a thread for a Shared Clipboard transfer.
  *
  * @returns VBox status code.
@@ -2347,5 +2351,5 @@
 
 /**
- * Destroys a thread of a clipboard Shared Clipboard transfer.
+ * Destroys a thread of a Shared Clipboard transfer.
  *
  * @returns VBox status code.
@@ -2374,5 +2378,5 @@
 
 /**
- * Initializes a clipboard Shared Clipboard transfer.
+ * Initializes a Shared Clipboard transfer.
  *
  * @returns VBox status code.
@@ -2402,5 +2406,5 @@
 
 /**
- * Destroys an Shared Clipboard transfer context context struct.
+ * Destroys a shared Clipboard transfer context context struct.
  *
  * @param   pTransferCtx                Transfer context to destroy.
@@ -2430,5 +2434,5 @@
 
 /**
- * Resets an clipboard Shared Clipboard transfer.
+ * Resets a shared Clipboard transfer.
  *
  * @param   pTransferCtx                Transfer context to reset.
@@ -2501,5 +2505,5 @@
 
 /**
- * Registers an Shared Clipboard transfer with a transfer context, i.e. allocates a transfer ID.
+ * Registers a shared Clipboard transfer with a transfer context, i.e. allocates a transfer ID.
  *
  * @return  VBox status code.
@@ -2554,5 +2558,5 @@
 
 /**
- * Registers an Shared Clipboard transfer with a transfer contextby specifying an ID for the transfer.
+ * Registers a shared Clipboard transfer with a transfer contextby specifying an ID for the transfer.
  *
  * @return  VBox status code.
@@ -2948,12 +2952,12 @@
  *
  * @returns Transfer status string name.
- * @param   uStatus             The transfer status to translate.
- */
-const char *VBoxShClTransferStatusToStr(uint32_t uStatus)
-{
-    switch (uStatus)
+ * @param   enmStatus           The transfer status to translate.
+ */
+const char *VBoxShClTransferStatusToStr(SHCLTRANSFERSTATUS enmStatus)
+{
+    switch (enmStatus)
     {
         RT_CASE_RET_STR(SHCLTRANSFERSTATUS_NONE);
-        RT_CASE_RET_STR(SHCLTRANSFERSTATUS_READY);
+        RT_CASE_RET_STR(SHCLTRANSFERSTATUS_INITIALIZED);
         RT_CASE_RET_STR(SHCLTRANSFERSTATUS_STARTED);
         RT_CASE_RET_STR(SHCLTRANSFERSTATUS_STOPPED);
Index: trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc-transfers.cpp
===================================================================
--- trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc-transfers.cpp	(revision 80904)
+++ trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc-transfers.cpp	(revision 80905)
@@ -90,5 +90,5 @@
 
         HGCMSvcSetU32(&pMsgHdr->paParms[0], VBOX_SHCL_CONTEXTID_MAKE(pClient->State.uSessionID,
-                                                                                   pCtx->pTransfer->State.uID, uEvent));
+                                                                     pCtx->pTransfer->State.uID, uEvent));
         HGCMSvcSetU32(&pMsgHdr->paParms[1], 0 /* fRoots */);
 
@@ -644,43 +644,4 @@
     LogFlowFuncLeaveRC(rc);
     return rc;
-}
-
-
-/*********************************************************************************************************************************
-*   transfer callbacks                                                                                                                *
-*********************************************************************************************************************************/
-
-DECLCALLBACK(void) VBoxSvcClipboardTransferPrepareCallback(PSHCLTRANSFERCALLBACKDATA pData)
-{
-    RT_NOREF(pData);
-
-    LogFlowFuncEnter();
-}
-
-DECLCALLBACK(void) VBoxSvcClipboardTransferCompleteCallback(PSHCLTRANSFERCALLBACKDATA pData, int rc)
-{
-    RT_NOREF(pData, rc);
-
-    LogFlowFuncEnter();
-
-    LogRel2(("Shared Clipboard: Transfer complete\n"));
-}
-
-DECLCALLBACK(void) VBoxSvcClipboardTransferCanceledCallback(PSHCLTRANSFERCALLBACKDATA pData)
-{
-    LogFlowFuncEnter();
-
-    RT_NOREF(pData);
-
-    LogRel2(("Shared Clipboard: Transfer canceled\n"));
-}
-
-DECLCALLBACK(void) VBoxSvcClipboardTransferErrorCallback(PSHCLTRANSFERCALLBACKDATA pData, int rc)
-{
-    LogFlowFuncEnter();
-
-    RT_NOREF(pData, rc);
-
-    LogRel(("Shared Clipboard: Transfer failed with %Rrc\n", rc));
 }
 
@@ -1373,5 +1334,5 @@
                         if (enmDir == SHCLTRANSFERDIR_READ)
                         {
-                            creationCtx.Interface.pfnGetRoots        = sharedClipboardSvcTransferGetRoots;
+                            creationCtx.Interface.pfnRootsGet        = sharedClipboardSvcTransferGetRoots;
                             creationCtx.Interface.pfnListHdrRead     = sharedClipboardSvcTransferListHdrRead;
                             creationCtx.Interface.pfnListEntryRead   = sharedClipboardSvcTransferListEntryRead;
@@ -2176,5 +2137,5 @@
                     creationCtx.Interface.pfnObjClose        = sharedClipboardSvcTransferObjClose;
 
-                    creationCtx.Interface.pfnGetRoots        = sharedClipboardSvcTransferGetRoots;
+                    creationCtx.Interface.pfnRootsGet        = sharedClipboardSvcTransferGetRoots;
                     creationCtx.Interface.pfnListHdrRead     = sharedClipboardSvcTransferListHdrRead;
                     creationCtx.Interface.pfnListEntryRead   = sharedClipboardSvcTransferListEntryRead;
@@ -2193,17 +2154,4 @@
             creationCtx.enmSource = pClient->State.enmSource;
             creationCtx.pvUser    = pClient;
-
-            /* Register needed callbacks so that we can wait for the meta data to arrive here. */
-            SHCLTRANSFERCALLBACKS Callbacks;
-            RT_ZERO(Callbacks);
-
-            Callbacks.pvUser                = pClient;
-
-            Callbacks.pfnTransferPrepare    = VBoxSvcClipboardTransferPrepareCallback;
-            Callbacks.pfnTransferComplete   = VBoxSvcClipboardTransferCompleteCallback;
-            Callbacks.pfnTransferCanceled   = VBoxSvcClipboardTransferCanceledCallback;
-            Callbacks.pfnTransferError      = VBoxSvcClipboardTransferErrorCallback;
-
-            SharedClipboardTransferSetCallbacks(pTransfer, &Callbacks);
 
             uint32_t uTransferID = 0;
@@ -2223,5 +2171,5 @@
                             SHCLEVENTID uEvent;
                             rc = sharedClipboardSvcTransferSendStatus(pClient, pTransfer,
-                                                                      SHCLTRANSFERSTATUS_READY, VINF_SUCCESS,
+                                                                      SHCLTRANSFERSTATUS_INITIALIZED, VINF_SUCCESS,
                                                                       &uEvent);
                             if (RT_SUCCESS(rc))
@@ -2240,5 +2188,5 @@
                                     Assert(pReply->uType == VBOX_SHCL_REPLYMSGTYPE_TRANSFER_STATUS);
 
-                                    if (pReply->u.TransferStatus.uStatus)
+                                    if (pReply->u.TransferStatus.uStatus == SHCLTRANSFERSTATUS_STARTED)
                                     {
                                         LogRel2(("Shared Clipboard: Started transfer %RU32 on guest\n", pTransfer->State.uID));
