Index: /trunk/include/VBox/GuestHost/SharedClipboard-transfers.h
===================================================================
--- /trunk/include/VBox/GuestHost/SharedClipboard-transfers.h	(revision 81211)
+++ /trunk/include/VBox/GuestHost/SharedClipboard-transfers.h	(revision 81212)
@@ -655,6 +655,7 @@
 
 int SharedClipboardTransferRootListEntryCopy(PSHCLROOTLISTENTRY pDst, PSHCLROOTLISTENTRY pSrc);
+int SharedClipboardTransferRootListEntryInit(PSHCLROOTLISTENTRY pRootListEntry);
+void SharedClipboardTransferRootListEntryDestroy(PSHCLROOTLISTENTRY pRootListEntry);
 PSHCLROOTLISTENTRY SharedClipboardTransferRootListEntryDup(PSHCLROOTLISTENTRY pRootListEntry);
-void SharedClipboardTransferRootListEntryDestroy(PSHCLROOTLISTENTRY pRootListEntry);
 
 int SharedClipboardTransferListHdrAlloc(PSHCLLISTHDR *ppListHdr);
@@ -1043,5 +1044,5 @@
 {
     /** Actual status to report. */
-    SHCLTRANSFERSTATUS uStatus;
+    SHCLTRANSFERSTATUS    uStatus;
     /** Result code (rc) to report; might be unused / invalid, based on enmStatus. */
     int                   rc;
@@ -1073,4 +1074,7 @@
 bool SharedClipboardTransferObjCtxIsValid(PSHCLCLIENTTRANSFEROBJCTX pObjCtx);
 
+int SharedClipboardTransferObjectHandleInfoInit(PSHCLOBJHANDLEINFO pInfo);
+void SharedClipboardTransferObjectHandleInfoDestroy(PSHCLOBJHANDLEINFO pInfo);
+
 int SharedClipboardTransferObjectOpenParmsInit(PSHCLOBJOPENCREATEPARMS pParms);
 int SharedClipboardTransferObjectOpenParmsCopy(PSHCLOBJOPENCREATEPARMS pParmsDst, PSHCLOBJOPENCREATEPARMS pParmsSrc);
Index: /trunk/include/VBox/GuestHost/SharedClipboard-win.h
===================================================================
--- /trunk/include/VBox/GuestHost/SharedClipboard-win.h	(revision 81211)
+++ /trunk/include/VBox/GuestHost/SharedClipboard-win.h	(revision 81212)
@@ -138,4 +138,5 @@
 
 #ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
+int SharedClipboardWinGetRoots(PSHCLWINCTX pWinCtx, PSHCLTRANSFER pTransfer);
 int SharedClipboardWinDropFilesToStringList(DROPFILES *pDropFiles, char **papszList, uint32_t *pcbList);
 #endif
Index: /trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxClipboard.cpp
===================================================================
--- /trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxClipboard.cpp	(revision 81211)
+++ /trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxClipboard.cpp	(revision 81212)
@@ -154,49 +154,37 @@
     if (enmDir == SHCLTRANSFERDIR_WRITE)
     {
-        Assert(SharedClipboardTransferGetSource(pTransfer) == SHCLSOURCE_LOCAL); /* Sanity. */
-
-        rc = SharedClipboardWinOpen(pCtx->Win.hWnd);
-        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
-                    LogRel(("Shared Clipboard: Unable to lock clipboard data, last error: %ld\n", GetLastError()));
-            }
-            else
-                LogRel(("Shared Clipboard: Unable to retrieve clipboard data from clipboard (CF_HDROP), last error: %ld\n",
-                        GetLastError()));
-
-            SharedClipboardWinClose();
-        }
+        rc = SharedClipboardWinGetRoots(&pCtx->Win, pTransfer);
     }
     /* The guest wants to read data from a remote source. */
     else if (enmDir == SHCLTRANSFERDIR_READ)
     {
-        Assert(SharedClipboardTransferGetSource(pTransfer) == SHCLSOURCE_REMOTE); /* Sanity. */
-
-        rc = SharedClipboardWinTransferCreate(&pCtx->Win, pTransfer);
+        /* The IDataObject *must* be created on the same thread as our (proxy) window, so post a message to it
+         * to do the stuff for us. */
+        const SHCLEVENTID uEvent = SharedClipboardEventIDGenerate(&pTransfer->Events);
+
+        rc = SharedClipboardEventRegister(&pTransfer->Events, uEvent);
+        if (RT_SUCCESS(rc))
+        {
+            /* Don't want to rely on SendMessage (synchronous) here, so just post and wait the event getting signalled. */
+            ::PostMessage(pCtx->Win.hWnd, SHCL_WIN_WM_TRANSFER_START, (WPARAM)pTransfer, (LPARAM)uEvent);
+
+            PSHCLEVENTPAYLOAD pPayload;
+            rc = SharedClipboardEventWait(&pTransfer->Events, uEvent, 30 * 1000 /* Timeout in ms */, &pPayload);
+            if (RT_SUCCESS(rc))
+            {
+                Assert(pPayload->cbData == sizeof(int));
+                rc = *(int *)pPayload->pvData;
+
+                SharedClipboardPayloadFree(pPayload);
+            }
+
+            SharedClipboardEventUnregister(&pTransfer->Events, uEvent);
+        }
     }
     else
         AssertFailedStmt(rc = VERR_NOT_SUPPORTED);
+
+    if (RT_FAILURE(rc))
+        LogRel(("Shared Clipboard: Starting transfer failed, rc=%Rrc\n", rc));
 
     LogFlowFunc(("LEAVE: idTransfer=%RU16, rc=%Rrc\n", SharedClipboardTransferGetID(pTransfer), rc));
@@ -651,19 +639,28 @@
         }
 
-#if 0
         case SHCL_WIN_WM_TRANSFER_START:
         {
             LogFunc(("SHCL_WIN_WM_TRANSFER_START\n"));
 
-            PSHCLTRANSFER pTransfer = (PSHCLTRANSFER)lParam;
+            PSHCLTRANSFER pTransfer  = (PSHCLTRANSFER)wParam;
             AssertPtr(pTransfer);
 
+            const SHCLEVENTID uEvent = (SHCLEVENTID)lParam;
+
             Assert(SharedClipboardTransferGetSource(pTransfer) == SHCLSOURCE_REMOTE); /* Sanity. */
 
-            int rc2 = SharedClipboardWinTransferCreate(pWinCtx, pTransfer);
-            AssertRC(rc2);
-            break;
-        }
-#endif
+            int rcTransfer = SharedClipboardWinTransferCreate(pWinCtx, pTransfer);
+
+            PSHCLEVENTPAYLOAD pPayload = NULL;
+            int rc = SharedClipboardPayloadAlloc(uEvent, &rcTransfer, sizeof(rcTransfer), &pPayload);
+            if (RT_SUCCESS(rc))
+            {
+                rc = SharedClipboardEventSignal(&pTransfer->Events, uEvent, pPayload);
+                if (RT_FAILURE(rc))
+                    SharedClipboardPayloadFree(pPayload);
+            }
+
+            break;
+        }
 
         case WM_DESTROY:
Index: /trunk/src/VBox/Additions/common/VBoxGuest/lib/VBoxGuestR3LibClipboard.cpp
===================================================================
--- /trunk/src/VBox/Additions/common/VBoxGuest/lib/VBoxGuestR3LibClipboard.cpp	(revision 81211)
+++ /trunk/src/VBox/Additions/common/VBoxGuest/lib/VBoxGuestR3LibClipboard.cpp	(revision 81212)
@@ -501,5 +501,11 @@
                     for (uint32_t i = 0; i < srcRootListHdr.cRoots; i++)
                     {
-                        rc = vbglR3ClipboardRootListEntryRead(pCtx, i, &pRootList->paEntries[i]);
+                        SHCLROOTLISTENTRY *pEntry = &pRootList->paEntries[i];
+                        AssertPtr(pEntry);
+
+                        rc = SharedClipboardTransferRootListEntryInit(pEntry);
+                        if (RT_SUCCESS(rc))
+                            rc = vbglR3ClipboardRootListEntryRead(pCtx, i, pEntry);
+
                         if (RT_FAILURE(rc))
                             break;
@@ -1266,5 +1272,5 @@
     Msg.uHandle.SetUInt64(0);
     Msg.cbPath.SetUInt32(pCreateParms->cbPath);
-    Msg.szPath.SetPtr((void *)pCreateParms->pszPath, pCreateParms->cbPath + 1 /* Include terminating zero */);
+    Msg.szPath.SetPtr((void *)pCreateParms->pszPath, pCreateParms->cbPath);
     Msg.fCreate.SetUInt32(pCreateParms->fCreate);
 
@@ -1440,8 +1446,8 @@
     Msg.uContext.SetUInt32(pCtx->uContextID);
     Msg.uHandle.SetUInt64(hObj);
+    Msg.cbData.SetUInt32(cbData);
     Msg.pvData.SetPtr(pvData, cbData);
-    Msg.cbData.SetUInt32(cbData);
+    Msg.cbChecksum.SetUInt32(0);
     Msg.pvChecksum.SetPtr(NULL, 0);
-    Msg.cbChecksum.SetUInt32(0);
 
     int rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg));
Index: /trunk/src/VBox/GuestHost/SharedClipboard/clipboard-transfers.cpp
===================================================================
--- /trunk/src/VBox/GuestHost/SharedClipboard/clipboard-transfers.cpp	(revision 81211)
+++ /trunk/src/VBox/GuestHost/SharedClipboard/clipboard-transfers.cpp	(revision 81212)
@@ -131,5 +131,6 @@
  *
  * @returns VBox status code.
- * @param   pListEntry          Clipboard root list entry to copy.
+ * @param   pDst                Where to copy the source root list entry to.
+ * @param   pSrc                Source root list entry to copy.
  */
 int SharedClipboardTransferRootListEntryCopy(PSHCLROOTLISTENTRY pDst, PSHCLROOTLISTENTRY pSrc)
@@ -139,22 +140,32 @@
 
 /**
+ * Initializes a clipboard root list entry structure.
+ *
+ * @param   pRootListEntry      Clipboard root list entry structure to destroy.
+ */
+int SharedClipboardTransferRootListEntryInit(PSHCLROOTLISTENTRY pRootListEntry)
+{
+    return SharedClipboardTransferListEntryInit(pRootListEntry);
+}
+
+/**
+ * Destroys a clipboard root list entry structure.
+ *
+ * @param   pRootListEntry      Clipboard root list entry structure to destroy.
+ */
+void SharedClipboardTransferRootListEntryDestroy(PSHCLROOTLISTENTRY pRootListEntry)
+{
+    return SharedClipboardTransferListEntryDestroy(pRootListEntry);
+}
+
+/**
  * Duplicates (allocates) a clipboard root list entry structure.
  *
  * @returns Duplicated clipboard root list entry structure on success.
- * @param   pListEntry          Clipboard root list entry to duplicate.
+ * @param   pRootListEntry      Clipboard root list entry to duplicate.
  */
 PSHCLROOTLISTENTRY SharedClipboardTransferRootListEntryDup(PSHCLROOTLISTENTRY pRootListEntry)
 {
     return SharedClipboardTransferListEntryDup(pRootListEntry);
-}
-
-/**
- * Destroys a clipboard root list entry structure.
- *
- * @param   pListEntry          Clipboard root list entry structure to destroy.
- */
-void SharedClipboardTransferRootListEntryDestroy(PSHCLROOTLISTENTRY pRootListEntry)
-{
-    return SharedClipboardTransferListEntryDestroy(pRootListEntry);
 }
 
@@ -517,9 +528,15 @@
 
     pListEntry->cbName = SHCLLISTENTRY_MAX_NAME;
-    pListEntry->pvInfo = NULL;
-    pListEntry->cbInfo = 0;
-    pListEntry->fInfo  = 0;
-
-    return VINF_SUCCESS;
+
+    pListEntry->pvInfo = (PSHCLFSOBJINFO)RTMemAlloc(sizeof(SHCLFSOBJINFO));
+    if (pListEntry->pvInfo)
+    {
+        pListEntry->cbInfo = sizeof(SHCLFSOBJINFO);
+        pListEntry->fInfo  = VBOX_SHCL_INFO_FLAG_FSOBJINFO;
+
+        return VINF_SUCCESS;
+    }
+
+    return VERR_NO_MEMORY;
 }
 
@@ -607,4 +624,24 @@
 
 /**
+ * Initializes an object handle info structure.
+ *
+ * @returns VBox status code.
+ * @param   pInfo               Object handle info structure to initialize.
+ */
+int SharedClipboardTransferObjectHandleInfoInit(PSHCLOBJHANDLEINFO pInfo)
+{
+    AssertPtrReturn(pInfo, VERR_INVALID_POINTER);
+
+    pInfo->hObj    = SHCLOBJHANDLE_INVALID;
+    pInfo->enmType = SHCLOBJTYPE_INVALID;
+
+    pInfo->pszPathLocalAbs = NULL;
+
+    RT_ZERO(pInfo->u);
+
+    return VINF_SUCCESS;
+}
+
+/**
  * Destroys an object handle info structure.
  *
@@ -743,22 +780,26 @@
         if (pInfo)
         {
-            const bool fWritable = true; /** @todo Fix this. */
-
-            uint64_t fOpen;
-            rc = sharedClipboardConvertFileCreateFlags(fWritable,
-                                                       pOpenCreateParms->fCreate, pOpenCreateParms->ObjInfo.Attr.fMode,
-                                                       SHCLOBJHANDLE_INVALID, &fOpen);
+            rc = SharedClipboardTransferObjectHandleInfoInit(pInfo);
             if (RT_SUCCESS(rc))
             {
-                char *pszPathAbs = RTStrAPrintf2("%s/%s", pTransfer->pszPathRootAbs, pOpenCreateParms->pszPath);
-                if (pszPathAbs)
+                const bool fWritable = true; /** @todo Fix this. */
+
+                uint64_t fOpen;
+                rc = sharedClipboardConvertFileCreateFlags(fWritable,
+                                                           pOpenCreateParms->fCreate, pOpenCreateParms->ObjInfo.Attr.fMode,
+                                                           SHCLOBJHANDLE_INVALID, &fOpen);
+                if (RT_SUCCESS(rc))
                 {
-                    LogFlowFunc(("%s\n", pszPathAbs));
-
-                    rc = RTFileOpen(&pInfo->u.Local.hFile, pszPathAbs, fOpen);
-                    RTStrFree(pszPathAbs);
+                    char *pszPathAbs = RTStrAPrintf2("%s/%s", pTransfer->pszPathRootAbs, pOpenCreateParms->pszPath);
+                    if (pszPathAbs)
+                    {
+                        LogFlowFunc(("%s\n", pszPathAbs));
+
+                        rc = RTFileOpen(&pInfo->u.Local.hFile, pszPathAbs, fOpen);
+                        RTStrFree(pszPathAbs);
+                    }
+                    else
+                        rc = VERR_NO_MEMORY;
                 }
-                else
-                    rc = VERR_NO_MEMORY;
             }
 
@@ -772,7 +813,9 @@
                 *phObj = pInfo->hObj;
             }
-
-            if (RT_FAILURE(rc))
+            else
+            {
+                SharedClipboardTransferObjectHandleInfoDestroy(pInfo);
                 RTMemFree(pInfo);
+            }
         }
         else
@@ -1746,18 +1789,12 @@
                                 && !fSkipEntry)
                             {
-                                pEntry->pvInfo = (PSHCLFSOBJINFO)RTMemAlloc(sizeof(SHCLFSOBJINFO));
-                                if (pEntry->pvInfo)
+                                rc = RTStrCopy(pEntry->pszName, pEntry->cbName, pDirEntry->szName);
+                                if (RT_SUCCESS(rc))
                                 {
-                                    rc = RTStrCopy(pEntry->pszName, pEntry->cbName, pDirEntry->szName);
-                                    if (RT_SUCCESS(rc))
-                                    {
-                                        SharedClipboardFsObjFromIPRT(PSHCLFSOBJINFO(pEntry->pvInfo), &pDirEntry->Info);
-
-                                        pEntry->cbInfo = sizeof(SHCLFSOBJINFO);
-                                        pEntry->fInfo  = VBOX_SHCL_INFO_FLAG_FSOBJINFO;
-                                    }
+                                    AssertPtr(pEntry->pvInfo);
+                                    Assert   (pEntry->cbInfo == sizeof(SHCLFSOBJINFO));
+
+                                    SharedClipboardFsObjFromIPRT(PSHCLFSOBJINFO(pEntry->pvInfo), &pDirEntry->Info);
                                 }
-                                else
-                                    rc = VERR_NO_MEMORY;
                             }
 
@@ -2033,10 +2070,10 @@
                 {
                     RTFSOBJINFO fsObjInfo;
-                    rc = RTPathQueryInfo(pcszSrcPath, & fsObjInfo, RTFSOBJATTRADD_NOTHING);
+                    rc = RTPathQueryInfo(pcszSrcPath, &fsObjInfo, RTFSOBJATTRADD_NOTHING);
                     if (RT_SUCCESS(rc))
                     {
                         SharedClipboardFsObjFromIPRT(PSHCLFSOBJINFO(pEntry->pvInfo), &fsObjInfo);
 
-                        pEntry->fInfo  = VBOX_SHCL_INFO_FLAG_FSOBJINFO;
+                        pEntry->fInfo = VBOX_SHCL_INFO_FLAG_FSOBJINFO;
                     }
                 }
@@ -2247,18 +2284,22 @@
 
 /**
- * Starts (runs) a Shared Clipboard transfer in a dedicated thread.
+ * Runs a started Shared Clipboard transfer in a dedicated thread.
  *
  * @returns VBox status code.
  * @param   pTransfer           Clipboard transfer to run.
  * @param   pfnThreadFunc       Pointer to thread function to use.
- * @param   pvUser              Pointer to user-provided data.
+ * @param   pvUser              Pointer to user-provided data. Optional.
  */
 int SharedClipboardTransferRun(PSHCLTRANSFER pTransfer, PFNRTTHREAD pfnThreadFunc, void *pvUser)
 {
-    AssertPtrReturn(pTransfer, VERR_INVALID_POINTER);
-
-    int rc = SharedClipboardTransferStart(pTransfer);
-    if (RT_SUCCESS(rc))
-        rc = sharedClipboardTransferThreadCreate(pTransfer, pfnThreadFunc, pvUser);
+    AssertPtrReturn(pTransfer,     VERR_INVALID_POINTER);
+    AssertPtrReturn(pfnThreadFunc, VERR_INVALID_POINTER);
+    /* pvUser is optional. */
+
+    AssertMsgReturn(pTransfer->State.enmStatus == SHCLTRANSFERSTATUS_STARTED,
+                    ("Wrong status (currently is %s)\n", VBoxShClTransferStatusToStr(pTransfer->State.enmStatus)),
+                    VERR_WRONG_ORDER);
+
+    int rc = sharedClipboardTransferThreadCreate(pTransfer, pfnThreadFunc, pvUser);
 
     LogFlowFuncLeaveRC(rc);
@@ -2275,4 +2316,6 @@
 {
     AssertPtrReturn(pTransfer, VERR_INVALID_POINTER);
+
+    LogFlowFuncEnter();
 
     /* Ready to start? */
@@ -2291,5 +2334,8 @@
         rc = VINF_SUCCESS;
 
-    /* Nothing else to do here right now. */
+    if (RT_SUCCESS(rc))
+    {
+        pTransfer->State.enmStatus = SHCLTRANSFERSTATUS_STARTED;
+    }
 
     LogFlowFuncLeaveRC(rc);
@@ -2342,4 +2388,11 @@
     AssertPtrReturn(pTransfer, VERR_INVALID_POINTER);
 
+    /* Already marked for stopping? */
+    AssertMsgReturn(pTransfer->Thread.fStop == false,
+                    ("Thransfer thread already marked for stopping"), VERR_WRONG_ORDER);
+    /* Already started? */
+    AssertMsgReturn(pTransfer->Thread.fStarted == false,
+                    ("Thransfer thread already started"), VERR_WRONG_ORDER);
+
     /* Spawn a worker thread, so that we don't block the window thread for too long. */
     int rc = RTThreadCreate(&pTransfer->Thread.hThread, pfnThreadFunc,
@@ -2353,5 +2406,5 @@
         if (pTransfer->Thread.fStarted) /* Did the thread indicate that it started correctly? */
         {
-            pTransfer->State.enmStatus = SHCLTRANSFERSTATUS_STARTED;
+            /* Nothing to do in here. */
         }
         else
@@ -2391,5 +2444,5 @@
 
 /**
- * Initializes a Shared Clipboard transfer.
+ * Initializes a Shared Clipboard transfer context.
  *
  * @returns VBox status code.
@@ -2407,6 +2460,7 @@
         RTListInit(&pTransferCtx->List);
 
+        pTransferCtx->cTransfers  = 0;
         pTransferCtx->cRunning    = 0;
-        pTransferCtx->cMaxRunning = UINT16_MAX;
+        pTransferCtx->cMaxRunning = UINT16_MAX; /** @todo Make this configurable? */
 
         RT_ZERO(pTransferCtx->bmTransferIds);
@@ -2419,5 +2473,5 @@
 
 /**
- * Destroys a shared Clipboard transfer context context struct.
+ * Destroys a shared Clipboard transfer context struct.
  *
  * @param   pTransferCtx                Transfer context to destroy.
@@ -2642,21 +2696,21 @@
                  pTransferCtx, pTransferCtx->cTransfers, pTransferCtx->cRunning));
 
-    if (!RTListIsEmpty(&pTransferCtx->List))
-    {
-        /* Remove all transfers which are not in a running state (e.g. only announced). */
-        PSHCLTRANSFER pTransfer, pTransferNext;
-        RTListForEachSafe(&pTransferCtx->List, pTransfer, pTransferNext, SHCLTRANSFER, Node)
-        {
-            if (SharedClipboardTransferGetStatus(pTransfer) != SHCLTRANSFERSTATUS_STARTED)
-            {
-                SharedClipboardTransferDestroy(pTransfer);
-                RTListNodeRemove(&pTransfer->Node);
-
-                RTMemFree(pTransfer);
-                pTransfer = NULL;
-
-                Assert(pTransferCtx->cTransfers);
-                pTransferCtx->cTransfers--;
-            }
+    if (pTransferCtx->cTransfers == 0)
+        return;
+
+    /* Remove all transfers which are not in a running state (e.g. only announced). */
+    PSHCLTRANSFER pTransfer, pTransferNext;
+    RTListForEachSafe(&pTransferCtx->List, pTransfer, pTransferNext, SHCLTRANSFER, Node)
+    {
+        if (SharedClipboardTransferGetStatus(pTransfer) != SHCLTRANSFERSTATUS_STARTED)
+        {
+            SharedClipboardTransferDestroy(pTransfer);
+            RTListNodeRemove(&pTransfer->Node);
+
+            RTMemFree(pTransfer);
+            pTransfer = NULL;
+
+            Assert(pTransferCtx->cTransfers);
+            pTransferCtx->cTransfers--;
         }
     }
Index: /trunk/src/VBox/GuestHost/SharedClipboard/clipboard-win.cpp
===================================================================
--- /trunk/src/VBox/GuestHost/SharedClipboard/clipboard-win.cpp	(revision 81211)
+++ /trunk/src/VBox/GuestHost/SharedClipboard/clipboard-win.cpp	(revision 81212)
@@ -459,6 +459,6 @@
         LogFlowFunc(("fFormats=0x%08X\n", fFormats));
 
-        pFormats->uFormats   = fFormats;
-        pFormats->fFlags = 0; /** @todo Handle flags. */
+        pFormats->uFormats = fFormats;
+        pFormats->fFlags   = 0; /** @todo Handle flags. */
     }
 
@@ -889,5 +889,5 @@
  * @returns VBox status code.
  * @param   pWinCtx             Windows context to use.
- * @param   pTransferCtxCtx             transfer contextto use.
+ * @param   pTransferCtxCtx     Transfer contextto use.
  * @param   pTransfer           Shared Clipboard transfer to use.
  */
@@ -1003,4 +1003,57 @@
 
 /**
+ * Retrieves the roots for a transfer by opening the clipboard and getting the clipboard data
+ * as string list (CF_HDROP), assigning it to the transfer as roots then.
+ *
+ * @returns VBox status code.
+ * @param   pWinCtx             Windows context to use.
+ * @param   pTransfer           Transfer to get roots for.
+ */
+int SharedClipboardWinGetRoots(PSHCLWINCTX pWinCtx, PSHCLTRANSFER pTransfer)
+{
+    AssertPtrReturn(pWinCtx,   VERR_INVALID_POINTER);
+    AssertPtrReturn(pTransfer, VERR_INVALID_POINTER);
+
+    Assert(SharedClipboardTransferGetSource(pTransfer) == SHCLSOURCE_LOCAL); /* Sanity. */
+
+    int rc = SharedClipboardWinOpen(pWinCtx->hWnd);
+    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
+                LogRel(("Shared Clipboard: Unable to lock clipboard data, last error: %ld\n", GetLastError()));
+        }
+        else
+            LogRel(("Shared Clipboard: Unable to retrieve clipboard data from clipboard (CF_HDROP), last error: %ld\n",
+                    GetLastError()));
+
+        SharedClipboardWinClose();
+    }
+
+    LogFlowFuncLeaveRC(rc);
+    return rc;
+}
+
+/**
  * Converts a DROPFILES (HDROP) structure to a string list, separated by \r\n.
  * Does not do any locking on the input data.
Index: /trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc-internal.h
===================================================================
--- /trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc-internal.h	(revision 81211)
+++ /trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc-internal.h	(revision 81212)
@@ -202,6 +202,6 @@
 #endif /* VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS */
 
-/*
- * Platform-dependent implementations.
+/** @name Platform-dependent implementations for the Shared Clipboard host service.
+ * @{
  */
 /**
@@ -258,6 +258,5 @@
 int ShClSvcImplWriteData(PSHCLCLIENT pClient, PSHCLCLIENTCMDCTX pCmdCtx, PSHCLDATABLOCK pData);
 /**
- * Synchronise the contents of the host clipboard with the guest, called by the HGCM layer
- * after a save and restore of the guest.
+ * Called when synchronization of the clipboard contents of the host clipboard with the guest is needed.
  *
  * @returns VBox status code.
@@ -265,11 +264,50 @@
  */
 int ShClSvcImplSync(PSHCLCLIENT pClient);
+/** @} */
 
 #ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
+/** @name Host implementations for Shared Clipboard transfers.
+ * @{
+ */
+/**
+ * Called when a transfer gets created.
+ *
+ * @returns VBox status code.
+ * @param   pClient             Shared Clipboard client context.
+ * @param   pTransfer           Shared Clipboard transfer created.
+ */
+int ShClSvcImplTransferCreate(PSHCLCLIENT pClient, PSHCLTRANSFER pTransfer);
+/**
+ * Called when a transfer gets destroyed.
+ *
+ * @returns VBox status code.
+ * @param   pClient             Shared Clipboard client context.
+ * @param   pTransfer           Shared Clipboard transfer to destroy.
+ */
+int ShClSvcImplTransferDestroy(PSHCLCLIENT pClient, PSHCLTRANSFER pTransfer);
+/**
+ * Called when getting (determining) the transfer roots on the host side.
+ *
+ * @returns VBox status code.
+ * @param   pClient             Shared Clipboard client context.
+ * @param   pTransfer           Shared Clipboard transfer to get roots for.
+ */
+int ShClSvcImplTransferGetRoots(PSHCLCLIENT pClient, PSHCLTRANSFER pTransfer);
+/** @} */
+#endif
+
+#ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
+/** @name Internal Shared Clipboard transfer host service functions.
+ * @{
+ */
 int shclSvcTransferAreaDetach(PSHCLCLIENTSTATE pClientState, PSHCLTRANSFER pTransfer);
 int shclSvcTransferHandler(PSHCLCLIENT pClient, VBOXHGCMCALLHANDLE callHandle, uint32_t u32Function,
                            uint32_t cParms, VBOXHGCMSVCPARM paParms[], uint64_t tsArrival);
 int shclSvcTransferHostHandler(uint32_t u32Function, uint32_t cParms, VBOXHGCMSVCPARM paParms[]);
-
+/** @} */
+
+/** @name Shared Clipboard transfer interface implementations for the host service.
+ * @{
+ */
 int shclSvcTransferIfaceOpen(PSHCLPROVIDERCTX pCtx);
 int shclSvcTransferIfaceClose(PSHCLPROVIDERCTX pCtx);
@@ -291,5 +329,9 @@
 int shclSvcTransferIfaceObjWrite(PSHCLPROVIDERCTX pCtx, SHCLOBJHANDLE hObj,
                                  void *pvData, uint32_t cbData, uint32_t fFlags, uint32_t *pcbWritten);
-
+/** @} */
+
+/** @name Shared Clipboard transfer callbacks for the host service.
+ * @{
+ */
 DECLCALLBACK(void) VBoxSvcClipboardTransferPrepareCallback(PSHCLTRANSFERCALLBACKDATA pData);
 DECLCALLBACK(void) VBoxSvcClipboardDataHeaderCompleteCallback(PSHCLTRANSFERCALLBACKDATA pData);
@@ -298,7 +340,5 @@
 DECLCALLBACK(void) VBoxSvcClipboardTransferCanceledCallback(PSHCLTRANSFERCALLBACKDATA pData);
 DECLCALLBACK(void) VBoxSvcClipboardTransferErrorCallback(PSHCLTRANSFERCALLBACKDATA pData, int rc);
-
-int ShClSvcImplTransferCreate(PSHCLCLIENT pClient, PSHCLTRANSFER pTransfer);
-int ShClSvcImplTransferDestroy(PSHCLCLIENT pClient, PSHCLTRANSFER pTransfer);
+/** @} */
 #endif /*VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS */
 
Index: /trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc-transfers.cpp
===================================================================
--- /trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc-transfers.cpp	(revision 81211)
+++ /trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc-transfers.cpp	(revision 81212)
@@ -1273,5 +1273,5 @@
 
 /**
- * transfer client (guest) handler for the Shared Clipboard host service.
+ * Transfer client (guest) handler for the Shared Clipboard host service.
  *
  * @returns VBox status code, or VINF_HGCM_ASYNC_EXECUTE if returning to the client will be deferred.
@@ -1420,5 +1420,5 @@
                 {
                     HGCMSvcSetPv (&paParms[3], rootListEntry.pszName, rootListEntry.cbName);
-                    HGCMSvcSetU32(&paParms[4], rootListEntry.cbName);
+                    HGCMSvcSetU32(&paParms[4], rootListEntry.cbInfo);
                     HGCMSvcSetPv (&paParms[5], rootListEntry.pvInfo, rootListEntry.cbInfo);
                 }
@@ -1569,7 +1569,34 @@
         }
 
-    #if 0
         case VBOX_SHCL_GUEST_FN_OBJ_OPEN:
         {
+            if (cParms != VBOX_SHCL_CPARMS_OBJ_OPEN)
+                break;
+
+            SHCLOBJOPENCREATEPARMS openCreateParms;
+            RT_ZERO(openCreateParms);
+
+            uint32_t cbPath;
+            rc = HGCMSvcGetU32(&paParms[2], &cbPath);
+            if (RT_SUCCESS(rc))
+            {
+                rc = HGCMSvcGetPv(&paParms[3], (void **)&openCreateParms.pszPath, &openCreateParms.cbPath);
+                if (cbPath != openCreateParms.cbPath)
+                    rc = VERR_INVALID_PARAMETER;
+            }
+            if (RT_SUCCESS(rc))
+                rc = HGCMSvcGetU32(&paParms[4], &openCreateParms.fCreate);
+
+            if (RT_SUCCESS(rc))
+            {
+                SHCLOBJHANDLE hObj;
+                rc = SharedClipboardTransferObjectOpen(pTransfer, &openCreateParms, &hObj);
+                if (RT_SUCCESS(rc))
+                {
+                    LogFlowFunc(("hObj=%RU64\n", hObj));
+
+                    HGCMSvcSetU64(&paParms[1], hObj);
+                }
+            }
             break;
         }
@@ -1577,4 +1604,11 @@
         case VBOX_SHCL_GUEST_FN_OBJ_CLOSE:
         {
+            if (cParms != VBOX_SHCL_CPARMS_OBJ_CLOSE)
+                break;
+
+            SHCLOBJHANDLE hObj;
+            rc = HGCMSvcGetU64(&paParms[1], &hObj); /* Get object handle. */
+            if (RT_SUCCESS(rc))
+                rc = SharedClipboardTransferObjectClose(pTransfer, hObj);
             break;
         }
@@ -1582,7 +1616,44 @@
         case VBOX_SHCL_GUEST_FN_OBJ_READ:
         {
-            break;
-        }
-    #endif
+            if (cParms != VBOX_SHCL_CPARMS_OBJ_READ)
+                break;
+
+            SHCLOBJHANDLE hObj;
+            rc = HGCMSvcGetU64(&paParms[1], &hObj); /* Get object handle. */
+
+            uint32_t cbToRead = 0;
+            if (RT_SUCCESS(rc))
+                rc = HGCMSvcGetU32(&paParms[2], &cbToRead);
+
+            void    *pvBuf = NULL;
+            uint32_t cbBuf = 0;
+            if (RT_SUCCESS(rc))
+                rc = HGCMSvcGetPv(&paParms[3], &pvBuf, &cbBuf);
+
+            LogFlowFunc(("hObj=%RU64, cbBuf=%RU32, cbToRead=%RU32, rc=%Rrc\n", hObj, cbBuf, cbToRead, rc));
+
+            if (   RT_SUCCESS(rc)
+                && (   !cbBuf
+                    || !cbToRead
+                    ||  cbBuf < cbToRead
+                   )
+               )
+            {
+                rc = VERR_INVALID_PARAMETER;
+            }
+
+            if (RT_SUCCESS(rc))
+            {
+                uint32_t cbRead;
+                rc = SharedClipboardTransferObjectRead(pTransfer, hObj, pvBuf, cbToRead, &cbRead, 0 /* fFlags */);
+                if (RT_SUCCESS(rc))
+                {
+                    HGCMSvcSetU32(&paParms[3], cbRead);
+
+                    /** @todo Implement checksum support. */
+                }
+            }
+            break;
+        }
 
         case VBOX_SHCL_GUEST_FN_OBJ_WRITE:
@@ -2106,45 +2177,45 @@
         if (RT_SUCCESS(rc))
         {
-            SHCLPROVIDERCREATIONCTX creationCtx;
-            RT_ZERO(creationCtx);
-
-            if (enmDir == SHCLTRANSFERDIR_READ)
-            {
-                rc = shclSvcTransferAreaRegister(&pClient->State, pTransfer);
-                if (RT_SUCCESS(rc))
-                {
-                    creationCtx.Interface.pfnTransferOpen  = shclSvcTransferIfaceOpen;
-                    creationCtx.Interface.pfnTransferClose = shclSvcTransferIfaceClose;
-
-                    creationCtx.Interface.pfnRootsGet      = shclSvcTransferIfaceGetRoots;
-
-                    creationCtx.Interface.pfnListOpen      = shclSvcTransferIfaceListOpen;
-                    creationCtx.Interface.pfnListClose     = shclSvcTransferIfaceListClose;
-                    creationCtx.Interface.pfnListHdrRead   = shclSvcTransferIfaceListHdrRead;
-                    creationCtx.Interface.pfnListEntryRead = shclSvcTransferIfaceListEntryRead;
-
-                    creationCtx.Interface.pfnObjOpen       = shclSvcTransferIfaceObjOpen;
-                    creationCtx.Interface.pfnObjClose      = shclSvcTransferIfaceObjClose;
-                    creationCtx.Interface.pfnObjRead       = shclSvcTransferIfaceObjRead;
-                }
-            }
-            else if (enmDir == SHCLTRANSFERDIR_WRITE)
-            {
-                creationCtx.Interface.pfnListHdrWrite   = shclSvcTransferIfaceListHdrWrite;
-                creationCtx.Interface.pfnListEntryWrite = shclSvcTransferIfaceListEntryWrite;
-                creationCtx.Interface.pfnObjWrite       = shclSvcTransferIfaceObjWrite;
-            }
-            else
-                AssertFailed();
-
-            creationCtx.enmSource = pClient->State.enmSource;
-            creationCtx.pvUser    = pClient;
-
-            uint32_t uTransferID = 0;
-
-            rc = SharedClipboardTransferSetInterface(pTransfer, &creationCtx);
-            if (RT_SUCCESS(rc))
-            {
-                rc = ShClSvcImplTransferCreate(pClient, pTransfer);
+            rc = ShClSvcImplTransferCreate(pClient, pTransfer);
+            if (RT_SUCCESS(rc))
+            {
+                SHCLPROVIDERCREATIONCTX creationCtx;
+                RT_ZERO(creationCtx);
+
+                if (enmDir == SHCLTRANSFERDIR_READ)
+                {
+                    rc = shclSvcTransferAreaRegister(&pClient->State, pTransfer);
+                    if (RT_SUCCESS(rc))
+                    {
+                        creationCtx.Interface.pfnTransferOpen  = shclSvcTransferIfaceOpen;
+                        creationCtx.Interface.pfnTransferClose = shclSvcTransferIfaceClose;
+
+                        creationCtx.Interface.pfnRootsGet      = shclSvcTransferIfaceGetRoots;
+
+                        creationCtx.Interface.pfnListOpen      = shclSvcTransferIfaceListOpen;
+                        creationCtx.Interface.pfnListClose     = shclSvcTransferIfaceListClose;
+                        creationCtx.Interface.pfnListHdrRead   = shclSvcTransferIfaceListHdrRead;
+                        creationCtx.Interface.pfnListEntryRead = shclSvcTransferIfaceListEntryRead;
+
+                        creationCtx.Interface.pfnObjOpen       = shclSvcTransferIfaceObjOpen;
+                        creationCtx.Interface.pfnObjClose      = shclSvcTransferIfaceObjClose;
+                        creationCtx.Interface.pfnObjRead       = shclSvcTransferIfaceObjRead;
+                    }
+                }
+                else if (enmDir == SHCLTRANSFERDIR_WRITE)
+                {
+                    creationCtx.Interface.pfnListHdrWrite   = shclSvcTransferIfaceListHdrWrite;
+                    creationCtx.Interface.pfnListEntryWrite = shclSvcTransferIfaceListEntryWrite;
+                    creationCtx.Interface.pfnObjWrite       = shclSvcTransferIfaceObjWrite;
+                }
+                else
+                    AssertFailed();
+
+                creationCtx.enmSource = pClient->State.enmSource;
+                creationCtx.pvUser    = pClient;
+
+                uint32_t uTransferID = 0;
+
+                rc = SharedClipboardTransferSetInterface(pTransfer, &creationCtx);
                 if (RT_SUCCESS(rc))
                 {
@@ -2155,37 +2226,52 @@
                         if (RT_SUCCESS(rc))
                         {
-                            SHCLEVENTID uEvent;
-                            rc = shclSvcTransferSendStatus(pClient, pTransfer,
-                                                           SHCLTRANSFERSTATUS_INITIALIZED, VINF_SUCCESS,
-                                                           &uEvent);
+                            if (   enmSource == SHCLSOURCE_LOCAL
+                                && enmDir    == SHCLTRANSFERDIR_WRITE) /* Get roots if this is a local write transfer. */
+                            {
+                                rc = ShClSvcImplTransferGetRoots(pClient, pTransfer);
+                            }
+
+                            if (RT_SUCCESS(rc))
+                                rc = SharedClipboardTransferStart(pTransfer);
+
                             if (RT_SUCCESS(rc))
                             {
-                                LogRel2(("Shared Clipboard: Waiting for start of transfer %RU32 on guest ...\n",
-                                         pTransfer->State.uID));
-
-                                PSHCLEVENTPAYLOAD pPayload;
-                                rc = SharedClipboardEventWait(&pTransfer->Events, uEvent, pTransfer->uTimeoutMs, &pPayload);
+                                SHCLEVENTID uEvent;
+                                rc = shclSvcTransferSendStatus(pClient, pTransfer,
+                                                               SHCLTRANSFERSTATUS_INITIALIZED, VINF_SUCCESS,
+                                                               &uEvent);
                                 if (RT_SUCCESS(rc))
                                 {
-                                    Assert(pPayload->cbData == sizeof(SHCLREPLY));
-                                    PSHCLREPLY pReply = (PSHCLREPLY)pPayload->pvData;
-                                    AssertPtr(pReply);
-
-                                    Assert(pReply->uType == VBOX_SHCL_REPLYMSGTYPE_TRANSFER_STATUS);
-
-                                    if (pReply->u.TransferStatus.uStatus == SHCLTRANSFERSTATUS_STARTED)
+                                    LogRel2(("Shared Clipboard: Waiting for start of transfer %RU32 on guest ...\n",
+                                             pTransfer->State.uID));
+
+                                    PSHCLEVENTPAYLOAD pPayload;
+                                    rc = SharedClipboardEventWait(&pTransfer->Events, uEvent, pTransfer->uTimeoutMs, &pPayload);
+                                    if (RT_SUCCESS(rc))
                                     {
-                                        LogRel2(("Shared Clipboard: Started transfer %RU32 on guest\n", pTransfer->State.uID));
+                                        Assert(pPayload->cbData == sizeof(SHCLREPLY));
+                                        PSHCLREPLY pReply = (PSHCLREPLY)pPayload->pvData;
+                                        AssertPtr(pReply);
+
+                                        Assert(pReply->uType == VBOX_SHCL_REPLYMSGTYPE_TRANSFER_STATUS);
+
+                                        if (pReply->u.TransferStatus.uStatus == SHCLTRANSFERSTATUS_STARTED)
+                                        {
+                                            LogRel2(("Shared Clipboard: Started transfer %RU32 on guest\n", pTransfer->State.uID));
+                                        }
+                                        else
+                                            LogRel(("Shared Clipboard: Guest reported status %s (error %Rrc) while starting transfer %RU32\n",
+                                                    VBoxShClTransferStatusToStr(pReply->u.TransferStatus.uStatus),
+                                                    pReply->rc, pTransfer->State.uID));
                                     }
                                     else
-                                        LogRel(("Shared Clipboard: Guest reported status %s (error %Rrc) while starting transfer %RU32\n",
-                                                VBoxShClTransferStatusToStr(pReply->u.TransferStatus.uStatus),
-                                                pReply->rc, pTransfer->State.uID));
+                                       LogRel(("Shared Clipboard: Unable to start transfer %RU32 on guest, rc=%Rrc\n",
+                                               pTransfer->State.uID, rc));
                                 }
-                                else
-                                   LogRel(("Shared Clipboard: Unable to start transfer %RU32 on guest, rc=%Rrc\n",
-                                           pTransfer->State.uID, rc));
                             }
                         }
+
+                        if (RT_FAILURE(rc))
+                            SharedClipboardTransferCtxTransferUnregister(&pClient->TransferCtx, uTransferID);
                     }
                 }
@@ -2194,6 +2280,5 @@
             if (RT_FAILURE(rc))
             {
-                SharedClipboardTransferCtxTransferUnregister(&pClient->TransferCtx, uTransferID);
-
+                ShClSvcImplTransferDestroy(pClient, pTransfer);
                 SharedClipboardTransferDestroy(pTransfer);
 
Index: /trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc-win.cpp
===================================================================
--- /trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc-win.cpp	(revision 81211)
+++ /trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc-win.cpp	(revision 81212)
@@ -888,4 +888,16 @@
     return VINF_SUCCESS;
 }
+
+int ShClSvcImplTransferGetRoots(PSHCLCLIENT pClient, PSHCLTRANSFER pTransfer)
+{
+    LogFlowFuncEnter();
+
+    const PSHCLWINCTX pWinCtx = &pClient->State.pCtx->Win;
+
+    int rc = SharedClipboardWinGetRoots(pWinCtx, pTransfer);
+
+    LogFlowFuncLeaveRC(rc);
+    return rc;
+}
 #endif /* VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS */
 
Index: /trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc-x11.cpp
===================================================================
--- /trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc-x11.cpp	(revision 81211)
+++ /trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc-x11.cpp	(revision 81212)
@@ -364,3 +364,9 @@
     return VINF_SUCCESS;
 }
+
+int ShClSvcImplTransferGetRoots(PSHCLCLIENT pClient, PSHCLTRANSFER pTransfer)
+{
+    RT_NOREF(pClient, pTransfer);
+    return VINF_SUCCESS;
+}
 #endif
Index: /trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc.cpp
===================================================================
--- /trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc.cpp	(revision 81211)
+++ /trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc.cpp	(revision 81212)
@@ -1181,9 +1181,9 @@
         if (RT_SUCCESS(rc))
         {
-            rc = ShClSvcImplConnect(pClient, ShClSvcGetHeadless());
 #ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
+            rc = SharedClipboardTransferCtxInit(&pClient->TransferCtx);
+#endif
             if (RT_SUCCESS(rc))
-                rc = SharedClipboardTransferCtxInit(&pClient->TransferCtx);
-#endif
+                rc = ShClSvcImplConnect(pClient, ShClSvcGetHeadless());
             if (RT_SUCCESS(rc))
             {
