Index: /trunk/include/VBox/GuestHost/SharedClipboard-win.h
===================================================================
--- /trunk/include/VBox/GuestHost/SharedClipboard-win.h	(revision 78473)
+++ /trunk/include/VBox/GuestHost/SharedClipboard-win.h	(revision 78474)
@@ -33,6 +33,9 @@
 #include <iprt/win/windows.h>
 
+#include <VBox/GuestHost/SharedClipboard.h>
+
 # ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
 #  include <iprt/cpp/ministring.h> /* For RTCString. */
+#  include <oleidl.h>
 # endif
 
@@ -41,7 +44,12 @@
 #endif
 
-#define VBOX_CLIPBOARD_WNDCLASS_NAME        "VBoxSharedClipboardClass"
-
-#define VBOX_CLIPBOARD_WIN_REGFMT_HTML      "VBox HTML Format"
+#define VBOX_CLIPBOARD_WNDCLASS_NAME         "VBoxSharedClipboardClass"
+
+/** See: https://docs.microsoft.com/en-us/windows/desktop/dataxchg/html-clipboard-format
+ *       Do *not* change the name, as this will break compatbility with other (legacy) applications! */
+#define VBOX_CLIPBOARD_WIN_REGFMT_HTML       "HTML Format"
+# ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
+#  define VBOX_CLIPBOARD_WIN_REGFMT_URI_LIST "VBoxURIList"
+#endif
 
 /** Default timeout (in ms) for passing down messages down the clipboard chain. */
@@ -80,4 +88,18 @@
     bool                   fCBChainPingInProcess;
 } VBOXCLIPBOARDWINAPIOLD, *PVBOXCLIPBOARDWINAPIOLD;
+
+#ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
+class VBoxClipboardWinDataObject;
+
+/**
+ * Structure for keeping URI clipboard information around.
+ */
+typedef struct _VBOXCLIPBOARDWINURI
+{
+    UINT cfFileGroupDescriptor;
+    UINT cfFileContents;
+    VBoxClipboardWinDataObject *pDataObj;
+} VBOXCLIPBOARDWINURI, *PVBOXCLIPBOARDWINURI;
+#endif
 
 typedef struct VBOXCLIPBOARDWINCTX
@@ -91,4 +113,8 @@
     /** Structure for maintaining the old clipboard API. */
     VBOXCLIPBOARDWINAPIOLD oldAPI;
+#ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
+    /** Structure for keeping URI clipboard information around. */
+    VBOXCLIPBOARDWINURI    URI;
+#endif
 } VBOXCLIPBOARDWINCTX, *PVBOXCLIPBOARDWINCTX;
 
@@ -101,8 +127,12 @@
 int VBoxClipboardWinRemoveFromCBChain(PVBOXCLIPBOARDWINCTX pCtx);
 VOID CALLBACK VBoxClipboardWinChainPingProc(HWND hWnd, UINT uMsg, ULONG_PTR dwData, LRESULT lResult);
-int VBoxClipboardWinGetFormats(PVBOXCLIPBOARDWINCTX pCtx, uint32_t *puFormats);
+VBOXCLIPBOARDFORMAT VBoxClipboardWinClipboardFormatToVBox(UINT uFormat);
+int VBoxClipboardWinGetFormats(PVBOXCLIPBOARDWINCTX pCtx, PVBOXCLIPBOARDFORMAT pfFormats);
 
 # ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
-class VBoxClipboardWinDataObject : public IDataObject
+class SharedClipboardURIList;
+class FILEGROUPDESCRIPTOR;
+
+class VBoxClipboardWinDataObject : public IDataObject //, public IDataObjectAsyncCapability
 {
 public:
@@ -111,8 +141,15 @@
     {
         Uninitialized = 0,
-        Initialized,
-        Dropping,
-        Dropped,
-        Aborted
+        Initialized
+    };
+
+    enum FormatIndex
+    {
+        /** File descriptor, ANSI version. */
+        FormatIndex_FileDescriptorA = 0,
+        /** File descriptor, Unicode version. */
+        FormatIndex_FileDescriptorW,
+        /** File contents. */
+        FormatIndex_FileContents
     };
 
@@ -140,17 +177,28 @@
     STDMETHOD(EnumDAdvise)(IEnumSTATDATA **ppEnumAdvise);
 
-public:
-
+#ifdef VBOX_WITH_SHARED_CLIPBOARD_WIN_ASYNC
+public: /* IDataObjectAsyncCapability methods. */
+
+    STDMETHOD(EndOperation)(HRESULT hResult, IBindCtx* pbcReserved, DWORD dwEffects);
+    STDMETHOD(GetAsyncMode)(BOOL* pfIsOpAsync);
+    STDMETHOD(InOperation)(BOOL* pfInAsyncOp);
+    STDMETHOD(SetAsyncMode)(BOOL fDoOpAsync);
+    STDMETHOD(StartOperation)(IBindCtx* pbcReserved);
+#endif /* VBOX_WITH_SHARED_CLIPBOARD_WIN_ASYNC */
+
+public:
+
+    int Init(uint32_t idClient);
     static const char* ClipboardFormatToString(CLIPFORMAT fmt);
 
-    int Abort(void);
-    void SetStatus(Status status);
-    int Signal(const RTCString &strFormat, const void *pvData, uint32_t cbData);
-
 protected:
 
-    bool LookupFormatEtc(LPFORMATETC pFormatEtc, ULONG *puIndex);
-    static HGLOBAL MemDup(HGLOBAL hMemSource);
-    void RegisterFormat(LPFORMATETC pFormatEtc, CLIPFORMAT clipFormat, TYMED tyMed = TYMED_HGLOBAL,
+    static int Thread(RTTHREAD hThread, void *pvUser);
+
+    int copyToHGlobal(const void *pvData, size_t cbData, UINT fFlags, HGLOBAL *phGlobal);
+    int createFileGroupDescriptor(const SharedClipboardURIList &URIList, HGLOBAL *phGlobal);
+
+    bool lookupFormatEtc(LPFORMATETC pFormatEtc, ULONG *puIndex);
+    void registerFormat(LPFORMATETC pFormatEtc, CLIPFORMAT clipFormat, TYMED tyMed = TYMED_HGLOBAL,
                         LONG lindex = -1, DWORD dwAspect = DVASPECT_CONTENT, DVTARGETDEVICE *pTargetDevice = NULL);
 
@@ -160,8 +208,7 @@
     LPFORMATETC mpFormatEtc;
     LPSTGMEDIUM mpStgMedium;
-    RTSEMEVENT  mEventDropped;
-    RTCString   mstrFormat;
-    void       *mpvData;
-    uint32_t    mcbData;
+    /** The HGCM client ID for the URI data transfers. */
+    uint32_t    muClientID;
+    IStream    *mpStream;
 };
 
@@ -173,9 +220,11 @@
     virtual ~VBoxClipboardWinEnumFormatEtc(void);
 
-public:
+public: /* IUnknown methods. */
 
     STDMETHOD(QueryInterface)(REFIID iid, void ** ppvObject);
     STDMETHOD_(ULONG, AddRef)(void);
     STDMETHOD_(ULONG, Release)(void);
+
+public: /* IEnumFORMATETC methods. */
 
     STDMETHOD(Next)(ULONG cFormats, LPFORMATETC pFormatEtc, ULONG *pcFetched);
@@ -197,10 +246,43 @@
 };
 
-#  if 0
-class VBoxClipboardWinStreamImpl : public IDataObject
-{
-
+/**
+ * Own IStream implementation to implement file-based clipboard operations
+ * through HGCM. Needed on Windows hosts and guests.
+ */
+class VBoxClipboardWinStreamImpl : public IStream
+{
+public:
+
+    VBoxClipboardWinStreamImpl(void);
+    virtual ~VBoxClipboardWinStreamImpl(void);
+
+public: /* IUnknown methods. */
+
+    STDMETHOD(QueryInterface)(REFIID iid, void ** ppvObject);
+    STDMETHOD_(ULONG, AddRef)(void);
+    STDMETHOD_(ULONG, Release)(void);
+
+public: /* IStream methods. */
+
+    STDMETHOD(Clone)(IStream** ppStream);
+    STDMETHOD(Commit)(DWORD dwFrags);
+    STDMETHOD(CopyTo)(IStream* pDestStream, ULARGE_INTEGER nBytesToCopy, ULARGE_INTEGER* nBytesRead, ULARGE_INTEGER* nBytesWritten);
+    STDMETHOD(LockRegion)(ULARGE_INTEGER nStart, ULARGE_INTEGER nBytes,DWORD dwFlags);
+    STDMETHOD(Read)(void* pvBuffer, ULONG nBytesToRead, ULONG* nBytesRead);
+    STDMETHOD(Revert)(void);
+    STDMETHOD(Seek)(LARGE_INTEGER nMove, DWORD dwOrigin, ULARGE_INTEGER* nNewPos);
+    STDMETHOD(SetSize)(ULARGE_INTEGER nNewSize);
+    STDMETHOD(Stat)(STATSTG* statstg, DWORD dwFlags);
+    STDMETHOD(UnlockRegion)(ULARGE_INTEGER nStart, ULARGE_INTEGER nBytes, DWORD dwFlags);
+    STDMETHOD(Write)(const void* pvBuffer, ULONG nBytesToRead, ULONG* nBytesRead);
+
+public: /* Own methods. */
+
+    static HRESULT Create(IStream **ppStream);
+
+private:
+
+    LONG        m_lRefCount;
 };
-#  endif
 
 # endif /* VBOX_WITH_SHARED_CLIPBOARD_URI_LIST */
Index: /trunk/include/VBox/GuestHost/SharedClipboard.h
===================================================================
--- /trunk/include/VBox/GuestHost/SharedClipboard.h	(revision 78473)
+++ /trunk/include/VBox/GuestHost/SharedClipboard.h	(revision 78474)
@@ -35,7 +35,11 @@
 /** A single Shared Clipboard format. */
 typedef uint32_t VBOXCLIPBOARDFORMAT;
+/** Pointer to a single Shared Clipboard format. */
+typedef VBOXCLIPBOARDFORMAT *PVBOXCLIPBOARDFORMAT;
 
 /** Bit map of Shared Clipboard format. */
 typedef uint32_t VBOXCLIPBOARDFORMATS;
+/** Pointer to a bit map of Shared Clipboard format. */
+typedef VBOXCLIPBOARDFORMATS *PVBOXCLIPBOARDFORMATS;
 
 /**
Index: /trunk/src/VBox/Additions/WINNT/VBoxTray/Makefile.kmk
===================================================================
--- /trunk/src/VBox/Additions/WINNT/VBoxTray/Makefile.kmk	(revision 78473)
+++ /trunk/src/VBox/Additions/WINNT/VBoxTray/Makefile.kmk	(revision 78474)
@@ -42,10 +42,10 @@
 	VBoxHelpers.cpp \
 	VBoxTray.rc
-VBoxTray_USES.win = vboximportchecker
+#VBoxTray_USES.win = vboximportchecker                  # !!! HACK ALERT !!! Fix this by using dynamic imports!
 VBoxTray_VBOX_IMPORT_CHECKER.win.x86 = nt4 #nt350
 VBoxTray_VBOX_IMPORT_CHECKER.win.amd64 = xp64
 ifdef VBOX_WITH_SHARED_CLIPBOARD
  VBoxTray_DEFS     += \
-	VBOX_WITH_SHARED_CLIPBOARD \
+	$(if $(VBOX_WITH_SHARED_CLIPBOARD),VBOX_WITH_SHARED_CLIPBOARD,) \
 	$(if $(VBOX_WITH_SHARED_CLIPBOARD_URI_LIST),VBOX_WITH_SHARED_CLIPBOARD_URI_LIST,)
  VBoxTray_SOURCES  += \
Index: /trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxClipboard.cpp
===================================================================
--- /trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxClipboard.cpp	(revision 78473)
+++ /trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxClipboard.cpp	(revision 78474)
@@ -29,7 +29,21 @@
 #include <VBox/GuestHost/SharedClipboard.h>
 #include <VBox/GuestHost/SharedClipboard-win.h>
+#ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
+# include <VBox/GuestHost/SharedClipboard-uri.h>
+#endif
 #include <strsafe.h>
 
 #include <VBox/log.h>
+
+
+#ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
+/** !!! HACK ALERT !!! Dynamically resolve functions! */
+#ifdef _WIN32_IE
+#undef _WIN32_IE
+#define _WIN32_IE 0x0501
+#endif
+#include <iprt/win/shlobj.h>
+#include <iprt/win/shlwapi.h>
+#endif
 
 
@@ -58,4 +72,5 @@
 
 
+
 static LRESULT vboxClipboardProcessMsg(PVBOXCLIPBOARDCONTEXT pCtx, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
 {
@@ -70,13 +85,13 @@
         case WM_CLIPBOARDUPDATE:
         {
-           Log(("WM_CLIPBOARDUPDATE\n"));
-
            if (GetClipboardOwner() != hwnd)
            {
+               Log(("WM_CLIPBOARDUPDATE\n"));
+
                /* Clipboard was updated by another application. */
-               uint32_t uFormats;
-               int vboxrc = VBoxClipboardWinGetFormats(&pCtx->Win, &uFormats);
+               VBOXCLIPBOARDFORMATS fFormats;
+               int vboxrc = VBoxClipboardWinGetFormats(&pCtx->Win, &fFormats);
                if (RT_SUCCESS(vboxrc))
-                   vboxrc = VbglR3ClipboardReportFormats(pCtx->u32ClientID, uFormats);
+                   vboxrc = VbglR3ClipboardReportFormats(pCtx->u32ClientID, fFormats);
            }
         }
@@ -119,21 +134,21 @@
         case WM_DRAWCLIPBOARD:
         {
-           LogFlowFunc(("WM_DRAWCLIPBOARD, hwnd %p\n", pWinCtx->hWnd));
-
-           if (GetClipboardOwner() != hwnd)
-           {
+            LogFlowFunc(("WM_DRAWCLIPBOARD, hwnd %p\n", pWinCtx->hWnd));
+
+            if (GetClipboardOwner() != hwnd)
+            {
                /* Clipboard was updated by another application. */
                /* WM_DRAWCLIPBOARD always expects a return code of 0, so don't change "rc" here. */
-               uint32_t uFormats;
-               int vboxrc = VBoxClipboardWinGetFormats(pWinCtx, &uFormats);
+               VBOXCLIPBOARDFORMATS fFormats;
+               int vboxrc = VBoxClipboardWinGetFormats(pWinCtx, &fFormats);
                if (RT_SUCCESS(vboxrc))
-                   vboxrc = VbglR3ClipboardReportFormats(pCtx->u32ClientID, uFormats);
-           }
-
-           if (pWinCtx->hWndNextInChain)
-           {
+                   vboxrc = VbglR3ClipboardReportFormats(pCtx->u32ClientID, fFormats);
+            }
+
+            if (pWinCtx->hWndNextInChain)
+            {
                /* Pass the message to next windows in the clipboard chain. */
                SendMessageTimeout(pWinCtx->hWndNextInChain, msg, wParam, lParam, 0, VBOX_CLIPBOARD_CBCHAIN_TIMEOUT_MS, NULL);
-           }
+            }
         }
         break;
@@ -141,25 +156,25 @@
         case WM_TIMER:
         {
-           if (VBoxClipboardWinIsNewAPI(&pWinCtx->newAPI))
-               break;
-
-           HWND hViewer = GetClipboardViewer();
-
-           /* Re-register ourselves in the clipboard chain if our last ping
+            if (VBoxClipboardWinIsNewAPI(&pWinCtx->newAPI))
+                break;
+
+            HWND hViewer = GetClipboardViewer();
+
+            /* Re-register ourselves in the clipboard chain if our last ping
             * timed out or there seems to be no valid chain. */
-           if (!hViewer || pWinCtx->oldAPI.fCBChainPingInProcess)
-           {
-               VBoxClipboardWinRemoveFromCBChain(pWinCtx);
-               VBoxClipboardWinAddToCBChain(pWinCtx);
-           }
-
-           /* Start a new ping by passing a dummy WM_CHANGECBCHAIN to be
+            if (!hViewer || pWinCtx->oldAPI.fCBChainPingInProcess)
+            {
+                VBoxClipboardWinRemoveFromCBChain(pWinCtx);
+                VBoxClipboardWinAddToCBChain(pWinCtx);
+            }
+
+            /* Start a new ping by passing a dummy WM_CHANGECBCHAIN to be
             * processed by ourselves to the chain. */
-           pWinCtx->oldAPI.fCBChainPingInProcess = TRUE;
-
-           hViewer = GetClipboardViewer();
-           if (hViewer)
-               SendMessageCallback(hViewer, WM_CHANGECBCHAIN, (WPARAM)pWinCtx->hWndNextInChain, (LPARAM)pWinCtx->hWndNextInChain,
-                                   VBoxClipboardWinChainPingProc, (ULONG_PTR)pWinCtx);
+            pWinCtx->oldAPI.fCBChainPingInProcess = TRUE;
+
+            hViewer = GetClipboardViewer();
+            if (hViewer)
+                SendMessageCallback(hViewer, WM_CHANGECBCHAIN, (WPARAM)pWinCtx->hWndNextInChain, (LPARAM)pWinCtx->hWndNextInChain,
+                                    VBoxClipboardWinChainPingProc, (ULONG_PTR)pWinCtx);
         }
         break;
@@ -167,5 +182,5 @@
         case WM_CLOSE:
         {
-           /* Do nothing. Ignore the message. */
+            /* Do nothing. Ignore the message. */
         }
         break;
@@ -173,183 +188,143 @@
         case WM_RENDERFORMAT:
         {
-           /* Insert the requested clipboard format data into the clipboard. */
-           uint32_t fFormat = VBOX_SHARED_CLIPBOARD_FMT_NONE;
-
-           const UINT cfFormat = (UINT)wParam;
-           switch (cfFormat)
-           {
-              case CF_UNICODETEXT:
-                  fFormat = VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT;
-                  break;
-
-              case CF_DIB:
-                  fFormat = VBOX_SHARED_CLIPBOARD_FMT_BITMAP;
-                  break;
-
-#ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
-              case CF_HDROP:
-                  fFormat = VBOX_SHARED_CLIPBOARD_FMT_URI_LIST;
-                  break;
-#endif
-              default:
-                  if (cfFormat >= 0xC000) /** @todo r=andy Explain. */
-                  {
-                      TCHAR szFormatName[256]; /** @todo r=andy Do we need Unicode support here as well? */
-
-                      int cActual = GetClipboardFormatName(cfFormat, szFormatName, sizeof(szFormatName) / sizeof(TCHAR));
-                      if (cActual)
-                      {
-                          if (strcmp(szFormatName, "HTML Format") == 0)
-                              fFormat = VBOX_SHARED_CLIPBOARD_FMT_HTML;
-                      }
-                  }
-                  break;
-           }
-
-           LogFunc(("WM_RENDERFORMAT: format=%u -> fFormat=0x%x\n", cfFormat, fFormat));
-
-           if (fFormat == VBOX_SHARED_CLIPBOARD_FMT_NONE)
-           {
-               /* Unsupported clipboard format is requested. */
-               LogRel(("Clipboard: Unsupported clipboard format requested (0x%x)\n", fFormat));
-               VBoxClipboardWinClear();
-           }
-#ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
-           else if (fFormat == VBOX_SHARED_CLIPBOARD_FMT_URI_LIST)
-           {
-
-           }
-#endif
-           else
-           {
-               const uint32_t cbPrealloc = _4K;
-               uint32_t cb = 0;
-
-               /* Preallocate a buffer, most of small text transfers will fit into it. */
-               HANDLE hMem = GlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE, cbPrealloc);
-               LogFlowFunc(("Preallocated handle hMem = %p\n", hMem));
-
-               if (hMem)
-               {
-                   void *pMem = GlobalLock(hMem);
-                   LogFlowFunc(("Locked pMem = %p, GlobalSize = %ld\n", pMem, GlobalSize(hMem)));
-
-                   if (pMem)
-                   {
-                       /* Read the host data to the preallocated buffer. */
-                       int vboxrc = VbglR3ClipboardReadData(pCtx->u32ClientID, fFormat, pMem, cbPrealloc, &cb);
-                       LogFlowFunc(("VbglR3ClipboardReadData returned with rc = %Rrc\n",  vboxrc));
-
-                       if (RT_SUCCESS(vboxrc))
-                       {
-                           if (cb == 0)
-                           {
-                               /* 0 bytes returned means the clipboard is empty.
-                                * Deallocate the memory and set hMem to NULL to get to
-                                * the clipboard empty code path. */
-                               GlobalUnlock(hMem);
-                               GlobalFree(hMem);
-                               hMem = NULL;
-                           }
-                           else if (cb > cbPrealloc)
-                           {
-                               GlobalUnlock(hMem);
-
-                               /* The preallocated buffer is too small, adjust the size. */
-                               hMem = GlobalReAlloc(hMem, cb, 0);
-                               LogFlowFunc(("Reallocated hMem = %p\n", hMem));
-
-                               if (hMem)
-                               {
-                                   pMem = GlobalLock(hMem);
-                                   LogFlowFunc(("Locked pMem = %p, GlobalSize = %ld\n", pMem, GlobalSize(hMem)));
-
-                                   if (pMem)
-                                   {
-                                       /* Read the host data to the preallocated buffer. */
-                                       uint32_t cbNew = 0;
-                                       vboxrc = VbglR3ClipboardReadData(pCtx->u32ClientID, fFormat, pMem, cb, &cbNew);
-                                       LogFlowFunc(("VbglR3ClipboardReadData returned with rc = %Rrc, cb = %d, cbNew = %d\n", vboxrc, cb, cbNew));
-
-                                       if (RT_SUCCESS(vboxrc) && cbNew <= cb)
-                                       {
-                                           cb = cbNew;
-                                       }
-                                       else
-                                       {
-                                           GlobalUnlock(hMem);
-                                           GlobalFree(hMem);
-                                           hMem = NULL;
-                                       }
-                                   }
-                                   else
-                                   {
-                                       GlobalFree(hMem);
-                                       hMem = NULL;
-                                   }
-                               }
-                           }
-
-                           if (hMem)
-                           {
-                               /* pMem is the address of the data. cb is the size of returned data. */
-                               /* Verify the size of returned text, the memory block for clipboard
-                                * must have the exact string size.
-                                */
-                               if (fFormat == VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT)
-                               {
-                                   size_t cbActual = 0;
-                                   HRESULT hrc = StringCbLengthW((LPWSTR)pMem, cb, &cbActual);
-                                   if (FAILED(hrc))
-                                   {
-                                       /* Discard invalid data. */
-                                       GlobalUnlock(hMem);
-                                       GlobalFree(hMem);
-                                       hMem = NULL;
-                                   }
-                                   else
-                                   {
-                                       /* cbActual is the number of bytes, excluding those used
-                                        * for the terminating null character.
-                                        */
-                                       cb = (uint32_t)(cbActual + 2);
-                                   }
-                               }
-                           }
-
-                           if (hMem)
-                           {
-                               GlobalUnlock(hMem);
-
-                               hMem = GlobalReAlloc(hMem, cb, 0);
-                               LogFlowFunc(("Reallocated hMem = %p\n", hMem));
-
-                               if (hMem)
-                               {
-                                   /* 'hMem' contains the host clipboard data.
-                                    * size is 'cb' and format is 'format'. */
-                                   HANDLE hClip = SetClipboardData(cfFormat, hMem);
-                                   LogFlowFunc(("WM_RENDERFORMAT hClip = %p\n", hClip));
-
-                                   if (hClip)
-                                   {
-                                       /* The hMem ownership has gone to the system. Finish the processing. */
-                                       break;
-                                   }
-
-                                   /* Cleanup follows. */
-                               }
-                           }
-                       }
-                       if (hMem)
-                           GlobalUnlock(hMem);
-                   }
-                   if (hMem)
-                       GlobalFree(hMem);
-               }
-
-               /* Something went wrong. */
-               VBoxClipboardWinClear();
-           }
+            LogFunc(("WM_RENDERFORMAT\n"));
+
+            /* Insert the requested clipboard format data into the clipboard. */
+            const UINT cfFormat = (UINT)wParam;
+
+            const VBOXCLIPBOARDFORMAT fFormat = VBoxClipboardWinClipboardFormatToVBox(cfFormat);
+
+            LogFunc(("WM_RENDERFORMAT: cfFormat=%u -> fFormat=0x%x\n", cfFormat, fFormat));
+
+            if (fFormat != VBOX_SHARED_CLIPBOARD_FMT_NONE)
+            {
+                const uint32_t cbPrealloc = _4K;
+                uint32_t cb = 0;
+
+                /* Preallocate a buffer, most of small text transfers will fit into it. */
+                HANDLE hMem = GlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE, cbPrealloc);
+                LogFlowFunc(("Preallocated handle hMem = %p\n", hMem));
+
+                if (hMem)
+                {
+                    void *pMem = GlobalLock(hMem);
+                    LogFlowFunc(("Locked pMem = %p, GlobalSize = %ld\n", pMem, GlobalSize(hMem)));
+
+                    if (pMem)
+                    {
+                        /* Read the host data to the preallocated buffer. */
+                        int vboxrc = VbglR3ClipboardReadData(pCtx->u32ClientID, fFormat, pMem, cbPrealloc, &cb);
+                        LogFlowFunc(("VbglR3ClipboardReadData returned with rc = %Rrc\n",  vboxrc));
+
+                        if (RT_SUCCESS(vboxrc))
+                        {
+                            if (cb == 0)
+                            {
+                                /* 0 bytes returned means the clipboard is empty.
+                                 * Deallocate the memory and set hMem to NULL to get to
+                                 * the clipboard empty code path. */
+                                GlobalUnlock(hMem);
+                                GlobalFree(hMem);
+                                hMem = NULL;
+                            }
+                            else if (cb > cbPrealloc)
+                            {
+                                GlobalUnlock(hMem);
+
+                                /* The preallocated buffer is too small, adjust the size. */
+                                hMem = GlobalReAlloc(hMem, cb, 0);
+                                LogFlowFunc(("Reallocated hMem = %p\n", hMem));
+
+                                if (hMem)
+                                {
+                                    pMem = GlobalLock(hMem);
+                                    LogFlowFunc(("Locked pMem = %p, GlobalSize = %ld\n", pMem, GlobalSize(hMem)));
+
+                                    if (pMem)
+                                    {
+                                        /* Read the host data to the preallocated buffer. */
+                                        uint32_t cbNew = 0;
+                                        vboxrc = VbglR3ClipboardReadData(pCtx->u32ClientID, fFormat, pMem, cb, &cbNew);
+                                        LogFlowFunc(("VbglR3ClipboardReadData returned with rc = %Rrc, cb = %d, cbNew = %d\n",
+                                                     vboxrc, cb, cbNew));
+
+                                        if (RT_SUCCESS(vboxrc)
+                                            && cbNew <= cb)
+                                        {
+                                            cb = cbNew;
+                                        }
+                                        else
+                                        {
+                                            GlobalUnlock(hMem);
+                                            GlobalFree(hMem);
+                                            hMem = NULL;
+                                        }
+                                    }
+                                    else
+                                    {
+                                        GlobalFree(hMem);
+                                        hMem = NULL;
+                                    }
+                                }
+                            }
+
+                            if (hMem)
+                            {
+                                /* pMem is the address of the data. cb is the size of returned data. */
+                                /* Verify the size of returned text, the memory block for clipboard
+                                 * must have the exact string size.
+                                 */
+                                if (fFormat == VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT)
+                                {
+                                    size_t cbActual = 0;
+                                    HRESULT hrc = StringCbLengthW((LPWSTR)pMem, cb, &cbActual);
+                                    if (FAILED(hrc))
+                                    {
+                                        /* Discard invalid data. */
+                                        GlobalUnlock(hMem);
+                                        GlobalFree(hMem);
+                                        hMem = NULL;
+                                    }
+                                    else
+                                    {
+                                        /* cbActual is the number of bytes, excluding those used
+                                         * for the terminating null character.
+                                         */
+                                        cb = (uint32_t)(cbActual + 2);
+                                    }
+                                }
+                            }
+
+                            if (hMem)
+                            {
+                                GlobalUnlock(hMem);
+
+                                hMem = GlobalReAlloc(hMem, cb, 0);
+                                LogFlowFunc(("Reallocated hMem = %p\n", hMem));
+
+                                if (hMem)
+                                {
+                                    /* 'hMem' contains the host clipboard data.
+                                     * size is 'cb' and format is 'format'. */
+                                    HANDLE hClip = SetClipboardData(cfFormat, hMem);
+                                    LogFlowFunc(("WM_RENDERFORMAT hClip = %p\n", hClip));
+
+                                    if (hClip)
+                                    {
+                                        /* The hMem ownership has gone to the system. Finish the processing. */
+                                        break;
+                                    }
+
+                                    /* Cleanup follows. */
+                                }
+                            }
+                        }
+                        if (hMem)
+                            GlobalUnlock(hMem);
+                    }
+                    if (hMem)
+                        GlobalFree(hMem);
+                }
+            }
         }
         break;
@@ -357,71 +332,104 @@
         case WM_RENDERALLFORMATS:
         {
-           /* Do nothing. The clipboard formats will be unavailable now, because the
+            /* Do nothing. The clipboard formats will be unavailable now, because the
             * windows is to be destroyed and therefore the guest side becomes inactive.
             */
+            int vboxrc = VBoxClipboardWinOpen(hwnd);
+            if (RT_SUCCESS(vboxrc))
+            {
+               VBoxClipboardWinClear();
+               VBoxClipboardWinClose();
+            }
+        }
+        break;
+
+        case VBOX_CLIPBOARD_WM_SET_FORMATS:
+        {
+           /* Announce available formats. Do not insert data, they will be inserted in WM_RENDER*. */
+           VBOXCLIPBOARDFORMATS fFormats = (uint32_t)lParam;
+
+           LogFunc(("VBOX_WM_SHCLPB_SET_FORMATS: fFormats=0x%x\n", fFormats));
+
            int vboxrc = VBoxClipboardWinOpen(hwnd);
            if (RT_SUCCESS(vboxrc))
            {
                VBoxClipboardWinClear();
+
+               HANDLE hClip    = NULL;
+               UINT   cfFormat = 0;
+
+               /** @todo r=andy Only one clipboard format can be set at once, at least on Windows. */
+
+               if (fFormats & VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT)
+               {
+                   LogFunc(("VBOX_WM_SHCLPB_SET_FORMATS: CF_UNICODETEXT\n"));
+                   hClip = SetClipboardData(CF_UNICODETEXT, NULL);
+               }
+
+               else if (fFormats & VBOX_SHARED_CLIPBOARD_FMT_BITMAP)
+               {
+                   LogFunc(("VBOX_WM_SHCLPB_SET_FORMATS: CF_DIB\n"));
+                   hClip = SetClipboardData(CF_DIB, NULL);
+               }
+
+               else if (fFormats & VBOX_SHARED_CLIPBOARD_FMT_HTML)
+               {
+                   LogFunc(("VBOX_WM_SHCLPB_SET_FORMATS: VBOX_CLIPBOARD_WIN_REGFMT_HTML\n"));
+                   cfFormat = RegisterClipboardFormat(VBOX_CLIPBOARD_WIN_REGFMT_HTML);
+                   if (cfFormat != 0)
+                       hClip = SetClipboardData(cfFormat, NULL);
+               }
+
+#ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
+               else if (fFormats & VBOX_SHARED_CLIPBOARD_FMT_URI_LIST)
+               {
+                   LogFunc(("VBOX_WM_SHCLPB_SET_FORMATS: VBOX_CLIPBOARD_WIN_REGFMT_URI_LIST\n"));
+                   if (pWinCtx->URI.pDataObj == NULL) /* Only allow one transfer at a time. */
+                   {
+                       pWinCtx->URI.pDataObj = new VBoxClipboardWinDataObject(/* No additional formats needed right now */);
+                       if (pWinCtx->URI.pDataObj)
+                       {
+                           int vboxrc = pWinCtx->URI.pDataObj->Init(pCtx->u32ClientID);
+                           if (RT_SUCCESS(vboxrc))
+                           {
+                               VBoxClipboardWinClose();
+                               /* Note: Clipboard must be closed first before calling OleSetClipboard(). */
+
+                               /** @todo There is a potential race between VBoxClipboardWinClose() and OleSetClipboard(),
+                                *        where another application could own the clipboard (open), and thus the call to
+                                *        OleSetClipboard() will fail. Needs fixing. */
+
+                               HRESULT hr = OleSetClipboard(pWinCtx->URI.pDataObj);
+                               if (FAILED(hr))
+                                   LogRel(("Clipboard: Failed with %Rhrc when setting data object to clipboard\n", hr));
+                           }
+                       }
+                   }
+               }
+#endif
+               else
+                   LogRel(("Clipboard: Unsupported format(s) (0x%x), skipping\n", fFormats));
+
+               /** @todo Implement more flexible clipboard precedence for supported formats. */
+
                VBoxClipboardWinClose();
+               /* Note: Clipboard must be closed first before calling OleSetClipboard(). */
+
+               LogFunc(("VBOX_WM_SHCLPB_SET_FORMATS: cfFormat=%u, lastErr=%ld\n", cfFormat, GetLastError()));
            }
         }
         break;
 
-        case VBOX_CLIPBOARD_WM_SET_FORMATS:
-        {
-           /* Announce available formats. Do not insert data, they will be inserted in WM_RENDER*. */
-           VBOXCLIPBOARDFORMATS fFormats = (uint32_t)lParam;
-
-           LogFlowFunc(("VBOX_WM_SHCLPB_SET_FORMATS: fFormats=0x%x\n", fFormats));
-
-           int vboxrc = VBoxClipboardWinOpen(hwnd);
-           if (RT_SUCCESS(vboxrc))
-           {
-               VBoxClipboardWinClear();
-
-               HANDLE hClip = NULL;
-
-               if (fFormats & VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT)
-                   hClip = SetClipboardData(CF_UNICODETEXT, NULL);
-
-               if (fFormats & VBOX_SHARED_CLIPBOARD_FMT_BITMAP)
-                   hClip = SetClipboardData(CF_DIB, NULL);
-
-               if (fFormats & VBOX_SHARED_CLIPBOARD_FMT_HTML)
-               {
-                   UINT format = RegisterClipboardFormat("HTML Format");
-                   if (format != 0)
-                       hClip = SetClipboardData(format, NULL);
-               }
-
-#ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
-               if (fFormats & VBOX_SHARED_CLIPBOARD_FMT_URI_LIST)
-                   hClip = SetClipboardData(CF_HDROP, NULL);
-#endif
-
-               /** @todo Implement more flexible clipboard precedence for supported formats. */
-
-               if (hClip == NULL)
-                   LogRel(("Clipboard: Unsupported format(s) from host (0x%x), ignoring\n", fFormats));
-
-               VBoxClipboardWinClose();
-
-               LogFlowFunc(("VBOX_WM_SHCLPB_SET_FORMATS: hClip=%p, lastErr=%ld\n", hClip, GetLastError()));
-           }
-        }
-        break;
-
         case VBOX_CLIPBOARD_WM_READ_DATA:
         {
-           /* Send data in the specified format to the host. */
-           uint32_t u32Formats = (uint32_t)lParam;
-           HANDLE hClip = NULL;
-
-           LogFlowFunc(("VBOX_WM_SHCLPB_READ_DATA: u32Formats=0x%x\n", u32Formats));
-
-           int vboxrc = VBoxClipboardWinOpen(hwnd);
-           if (RT_SUCCESS(vboxrc))
-           {
+            /* Send data in the specified format to the host. */
+            uint32_t u32Formats = (uint32_t)lParam;
+            HANDLE hClip = NULL;
+
+            LogFlowFunc(("VBOX_WM_SHCLPB_READ_DATA: u32Formats=0x%x\n", u32Formats));
+
+            int vboxrc = VBoxClipboardWinOpen(hwnd);
+            if (RT_SUCCESS(vboxrc))
+            {
                if (u32Formats & VBOX_SHARED_CLIPBOARD_FMT_BITMAP)
                {
@@ -465,5 +473,5 @@
                else if (u32Formats & VBOX_SHARED_CLIPBOARD_FMT_HTML)
                {
-                   UINT format = RegisterClipboardFormat("HTML Format");
+                   UINT format = RegisterClipboardFormat(VBOX_CLIPBOARD_WIN_REGFMT_HTML);
                    if (format != 0)
                    {
@@ -489,17 +497,21 @@
                else if (u32Formats & VBOX_SHARED_CLIPBOARD_FMT_URI_LIST)
                {
-                   hClip = GetClipboardData(CF_HDROP);
-                   if (hClip)
+                   UINT format = RegisterClipboardFormat(VBOX_CLIPBOARD_WIN_REGFMT_URI_LIST);
+                   if (format != 0)
                    {
-                       HDROP hDrop = (HDROP)GlobalLock(hClip);
-                       if (hDrop)
+                       hClip = GetClipboardData(format);
+                       if (hClip)
                        {
-       /*                    vboxrc = VbglR3ClipboardWriteData(pCtx->u32ClientID, VBOX_SHARED_CLIPBOARD_FMT_URI_LIST,
-                                                             );*/
-                           GlobalUnlock(hClip);
-                       }
-                       else
-                       {
-                           hClip = NULL;
+                           HDROP hDrop = (HDROP)GlobalLock(hClip);
+                           if (hDrop)
+                           {
+            /*                    vboxrc = VbglR3ClipboardWriteData(pCtx->u32ClientID, VBOX_SHARED_CLIPBOARD_FMT_URI_LIST,
+                                                                 );*/
+                               GlobalUnlock(hClip);
+                           }
+                           else
+                           {
+                               hClip = NULL;
+                           }
                        }
                    }
@@ -507,11 +519,11 @@
 #endif
                VBoxClipboardWinClose();
-           }
-
-           if (hClip == NULL)
-           {
+            }
+
+            if (hClip == NULL)
+            {
                /* Requested clipboard format is not available, send empty data. */
-               VbglR3ClipboardWriteData(pCtx->u32ClientID, 0, NULL, 0);
-           }
+               VbglR3ClipboardWriteData(pCtx->u32ClientID, VBOX_SHARED_CLIPBOARD_FMT_NONE, NULL, 0);
+            }
         }
         break;
@@ -519,8 +531,8 @@
         case WM_DESTROY:
         {
-           VBoxClipboardWinRemoveFromCBChain(pWinCtx);
-           if (pWinCtx->oldAPI.timerRefresh)
+            VBoxClipboardWinRemoveFromCBChain(pWinCtx);
+            if (pWinCtx->oldAPI.timerRefresh)
                KillTimer(pWinCtx->hWnd, 0);
-           /*
+            /*
             * don't need to call PostQuitMessage cause
             * the VBoxTray already finished a message loop
@@ -531,5 +543,5 @@
         default:
         {
-           rc = DefWindowProc(hwnd, msg, wParam, lParam);
+            rc = DefWindowProc(hwnd, msg, wParam, lParam);
         }
         break;
@@ -643,4 +655,15 @@
     }
 
+#ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
+    HRESULT hr = OleInitialize(NULL);
+    if (FAILED(hr))
+    {
+        LogRel(("Clipboard: Initializing OLE failed (%Rhrc) -- file transfers unavailable\n"));
+        /* Not critical, the rest of the clipboard might work. */
+    }
+    else
+        LogRel(("Clipboard: Initialized OLE\n"));
+#endif
+
     RT_BZERO(pCtx, sizeof(VBOXCLIPBOARDCONTEXT));
 
@@ -782,4 +805,9 @@
     vboxClipboardDestroy(pCtx);
     RT_BZERO(pCtx, sizeof(VBOXCLIPBOARDCONTEXT));
+
+#ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST_ASF
+    OleSetClipboard(NULL); /* Make sure to flush the clipboard on destruction. */
+    OleUninitialize();
+#endif
 
     return;
Index: /trunk/src/VBox/GuestHost/SharedClipboard/ClipboardDataObjectImpl-win.cpp
===================================================================
--- /trunk/src/VBox/GuestHost/SharedClipboard/ClipboardDataObjectImpl-win.cpp	(revision 78473)
+++ /trunk/src/VBox/GuestHost/SharedClipboard/ClipboardDataObjectImpl-win.cpp	(revision 78474)
@@ -22,8 +22,15 @@
 #define LOG_GROUP LOG_GROUP_SHARED_CLIPBOARD
 #include <VBox/GuestHost/SharedClipboard-win.h>
+#include <VBox/GuestHost/SharedClipboard-uri.h>
+
+/** !!! HACK ALERT !!! Dynamically resolve functions! */
+#ifdef _WIN32_IE
+#undef _WIN32_IE
+#define _WIN32_IE 0x0501
+#endif
 
 #include <iprt/win/windows.h>
-#include <new> /* For bad_alloc. */
 #include <iprt/win/shlobj.h>
+#include <iprt/win/shlwapi.h>
 
 #include <iprt/path.h>
@@ -32,17 +39,17 @@
 #include <iprt/utf16.h>
 
+#include <VBox/err.h>
 #include <VBox/log.h>
 
 VBoxClipboardWinDataObject::VBoxClipboardWinDataObject(LPFORMATETC pFormatEtc, LPSTGMEDIUM pStgMed, ULONG cFormats)
-    : mStatus(Uninitialized),
-      mRefCount(1),
-      mcFormats(0),
-      mpvData(NULL),
-      mcbData(0)
+    : mStatus(Uninitialized)
+    , mRefCount(0)
+    , mcFormats(0)
+    , muClientID(0)
 {
     HRESULT hr;
 
-    ULONG cFixedFormats = 1;
-    ULONG cAllFormats   = cFormats + cFixedFormats;
+    const ULONG cFixedFormats = 3; /* CFSTR_FILEDESCRIPTORA + CFSTR_FILEDESCRIPTORW + CFSTR_FILECONTENTS */
+    const ULONG cAllFormats   = cFormats + cFixedFormats;
 
     try
@@ -52,4 +59,19 @@
         mpStgMedium = new STGMEDIUM[cAllFormats];
         RT_BZERO(mpStgMedium, sizeof(STGMEDIUM) * cAllFormats);
+
+        /** @todo Do we need CFSTR_FILENAME / CFSTR_SHELLIDLIST here? */
+
+        /*
+         * Register fixed formats.
+         */
+
+        /* IStream interface, implemented in ClipboardStreamImpl-win.cpp. */
+        registerFormat(&mpFormatEtc[FormatIndex_FileDescriptorA],
+                       RegisterClipboardFormat(CFSTR_FILEDESCRIPTORA));
+        registerFormat(&mpFormatEtc[FormatIndex_FileDescriptorW],
+                       RegisterClipboardFormat(CFSTR_FILEDESCRIPTORW));
+        registerFormat(&mpFormatEtc[FormatIndex_FileContents],
+                       RegisterClipboardFormat(CFSTR_FILECONTENTS),
+                       TYMED_ISTREAM, 0 /* lIndex */);
 
         /*
@@ -66,6 +88,6 @@
                 LogFlowFunc(("Format %RU32: cfFormat=%RI16, tyMed=%RU32, dwAspect=%RU32\n",
                              i, pFormatEtc[i].cfFormat, pFormatEtc[i].tymed, pFormatEtc[i].dwAspect));
-                mpFormatEtc[i] = pFormatEtc[i];
-                mpStgMedium[i] = pStgMed[i];
+                mpFormatEtc[cFixedFormats + i] = pFormatEtc[i];
+                mpStgMedium[cFixedFormats + i] = pStgMed[i];
             }
         }
@@ -80,41 +102,16 @@
     if (SUCCEEDED(hr))
     {
-        int rc2 = RTSemEventCreate(&mEventDropped);
-        AssertRC(rc2);
-
-        /*
-         * Register fixed formats.
-         */
-#if 0
-        /* CF_HDROP. */
-        RegisterFormat(&mpFormatEtc[cFormats], CF_HDROP);
-        mpStgMedium[cFormats++].tymed = TYMED_HGLOBAL;
-
-        /* IStream. */
-        RegisterFormat(&mpFormatEtc[cFormats++],
-                       RegisterClipboardFormat(CFSTR_FILEDESCRIPTOR));
-        RegisterFormat(&mpFormatEtc[cFormats++],
-                       RegisterClipboardFormat(CFSTR_FILECONTENTS),
-                       TYMED_ISTREAM, 0 /* lIndex */);
-
-        /* Required for e.g. Windows Media Player. */
-        RegisterFormat(&mpFormatEtc[cFormats++],
-                       RegisterClipboardFormat(CFSTR_FILENAME));
-        RegisterFormat(&mpFormatEtc[cFormats++],
-                       RegisterClipboardFormat(CFSTR_FILENAMEW));
-        RegisterFormat(&mpFormatEtc[cFormats++],
-                       RegisterClipboardFormat(CFSTR_SHELLIDLIST));
-        RegisterFormat(&mpFormatEtc[cFormats++],
-                       RegisterClipboardFormat(CFSTR_SHELLIDLISTOFFSET));
-#endif
-        mcFormats = cFormats;
+        mcFormats = cAllFormats;
         mStatus   = Initialized;
     }
 
-    LogFlowFunc(("cFormats=%RU32, hr=%Rhrc\n", cFormats, hr));
+    LogFlowFunc(("cAllFormats=%RU32, hr=%Rhrc\n", cAllFormats, hr));
 }
 
 VBoxClipboardWinDataObject::~VBoxClipboardWinDataObject(void)
 {
+    if (mpStream)
+        mpStream->Release();
+
     if (mpFormatEtc)
         delete[] mpFormatEtc;
@@ -123,7 +120,4 @@
         delete[] mpStgMedium;
 
-    if (mpvData)
-        RTMemFree(mpvData);
-
     LogFlowFunc(("mRefCount=%RI32\n", mRefCount));
 }
@@ -135,5 +129,7 @@
 STDMETHODIMP_(ULONG) VBoxClipboardWinDataObject::AddRef(void)
 {
-    return InterlockedIncrement(&mRefCount);
+    LONG lCount = InterlockedIncrement(&mRefCount);
+    LogFlowFunc(("lCount=%RI32\n", lCount));
+    return lCount;
 }
 
@@ -141,4 +137,5 @@
 {
     LONG lCount = InterlockedDecrement(&mRefCount);
+    LogFlowFunc(("lCount=%RI32\n", mRefCount));
     if (lCount == 0)
     {
@@ -164,4 +161,97 @@
     *ppvObject = 0;
     return E_NOINTERFACE;
+}
+
+int VBoxClipboardWinDataObject::copyToHGlobal(const void *pvData, size_t cbData, UINT fFlags, HGLOBAL *phGlobal)
+{
+    AssertPtrReturn(phGlobal, VERR_INVALID_POINTER);
+
+    HGLOBAL hGlobal = GlobalAlloc(fFlags, cbData);
+    if (!hGlobal)
+        return VERR_NO_MEMORY;
+
+    void *pvAlloc = GlobalLock(hGlobal);
+    if (pvAlloc)
+    {
+        CopyMemory(pvAlloc, pvData, cbData);
+        GlobalUnlock(hGlobal);
+
+        *phGlobal = hGlobal;
+
+        return VINF_SUCCESS;
+    }
+
+    GlobalFree(hGlobal);
+    return VERR_ACCESS_DENIED;
+}
+
+int VBoxClipboardWinDataObject::createFileGroupDescriptor(const SharedClipboardURIList &URIList, HGLOBAL *phGlobal)
+{
+//    AssertReturn(URIList.GetRootCount(), VERR_INVALID_PARAMETER);
+    AssertPtrReturn(phGlobal, VERR_INVALID_POINTER);
+
+    int rc;
+
+    const size_t cItems = 2;  URIList.GetRootCount();
+    const size_t cbFGD  = sizeof(FILEGROUPDESCRIPTOR) + sizeof(FILEDESCRIPTOR) * (cItems - 1);
+
+    LogFunc(("cItmes=%zu\n", cItems));
+
+    FILEGROUPDESCRIPTOR *pFGD = (FILEGROUPDESCRIPTOR *)RTMemAlloc(cbFGD);
+    if (pFGD)
+    {
+        pFGD->cItems = (UINT)cItems;
+
+
+        FILEDESCRIPTOR *pFD = &pFGD->fgd[0];
+        RT_BZERO(pFD, sizeof(FILEDESCRIPTOR));
+
+        RTStrPrintf(pFD->cFileName, sizeof(pFD->cFileName), "barbaz.txt\n");
+
+    #if 1
+        pFD->dwFlags          = FD_ATTRIBUTES | FD_FILESIZE | FD_PROGRESSUI;
+        pFD->dwFileAttributes = FILE_ATTRIBUTE_NORMAL; // FILE_ATTRIBUTE_DIRECTORY;
+
+        uint64_t cbSize = _1M;
+
+        pFD->nFileSizeHigh    = RT_HI_U32(cbSize);
+        pFD->nFileSizeLow     = RT_LO_U32(cbSize);
+    #else
+        pFD->dwFlags = FD_ATTRIBUTES | FD_CREATETIME | FD_ACCESSTIME | FD_WRITESTIME | FD_FILESIZE;
+        pFD->dwFileAttributes =
+        pFD->ftCreationTime   =
+        pFD->ftLastAccessTime =
+        pFD->ftLastWriteTime  =
+        pFD->nFileSizeHigh    =
+        pFD->nFileSizeLow     =
+    #endif
+
+
+
+        pFD = &pFGD->fgd[1];
+        RT_BZERO(pFD, sizeof(FILEDESCRIPTOR));
+
+        RTStrPrintf(pFD->cFileName, sizeof(pFD->cFileName), "barbaz_dir\n");
+
+    #if 1
+        pFD->dwFlags          = FD_ATTRIBUTES | FD_PROGRESSUI;
+        pFD->dwFileAttributes = FILE_ATTRIBUTE_NORMAL | FILE_ATTRIBUTE_DIRECTORY;
+    #else
+        pFD->dwFlags = FD_ATTRIBUTES | FD_CREATETIME | FD_ACCESSTIME | FD_WRITESTIME | FD_FILESIZE;
+        pFD->dwFileAttributes =
+        pFD->ftCreationTime   =
+        pFD->ftLastAccessTime =
+        pFD->ftLastWriteTime  =
+        pFD->nFileSizeHigh    =
+        pFD->nFileSizeLow     =
+    #endif
+
+
+        rc = copyToHGlobal(pFGD, cbFGD, GMEM_MOVEABLE, phGlobal);
+    }
+    else
+        rc = VERR_NO_MEMORY;
+
+    return rc;
 }
 
@@ -180,9 +270,11 @@
     AssertPtrReturn(pMedium, DV_E_FORMATETC);
 
+    LogFlowFuncEnter();
+
     ULONG lIndex;
-    if (!LookupFormatEtc(pFormatEtc, &lIndex)) /* Format supported? */
+    if (!lookupFormatEtc(pFormatEtc, &lIndex)) /* Format supported? */
         return DV_E_FORMATETC;
     if (lIndex >= mcFormats) /* Paranoia. */
-        return DV_E_FORMATETC;
+        return DV_E_LINDEX;
 
     LPFORMATETC pThisFormat = &mpFormatEtc[lIndex];
@@ -196,228 +288,69 @@
     HRESULT hr = DV_E_FORMATETC; /* Play safe. */
 
-    LogFlowFunc(("mStatus=%ld\n", mStatus));
-    if (mStatus == Dropping)
-    {
-        LogRel2(("Clipboard: Waiting for drop event ...\n"));
-        int rc2 = RTSemEventWait(mEventDropped, RT_INDEFINITE_WAIT);
-        LogFlowFunc(("rc2=%Rrc, mStatus=%ld\n", rc2, mStatus)); RT_NOREF(rc2);
-    }
-
-    if (mStatus == Dropped)
-    {
-        LogRel2(("Clipboard: Drop event received\n"));
-        LogRel3(("Clipboard: cfFormat=%RI16, sFormat=%s, tyMed=%RU32, dwAspect=%RU32\n",
-                 pThisFormat->cfFormat, VBoxClipboardWinDataObject::ClipboardFormatToString(pFormatEtc->cfFormat),
-                 pThisFormat->tymed, pThisFormat->dwAspect));
-        LogRel3(("Clipboard: Got strFormat=%s, pvData=%p, cbData=%RU32\n",
-                  mstrFormat.c_str(), mpvData, mcbData));
-
-        /*
-         * Initialize default values.
-         */
+    LogRel3(("Clipboard: cfFormat=%RI16, sFormat=%s, tyMed=%RU32, dwAspect=%RU32 -> lIndex=%u\n",
+             pThisFormat->cfFormat, VBoxClipboardWinDataObject::ClipboardFormatToString(pFormatEtc->cfFormat),
+             pThisFormat->tymed, pThisFormat->dwAspect, lIndex));
+
+    /*
+     * Initialize default values.
+     */
+    pMedium->tymed          = pThisFormat->tymed;
+    pMedium->pUnkForRelease = NULL; /* Caller is responsible for deleting the data. */
+
+    switch (lIndex)
+    {
+        case FormatIndex_FileDescriptorA:
+        {
+            LogFlowFunc(("FormatIndex_FileDescriptorA\n"));
+
+            SharedClipboardURIList mURIList;
+           // mURIList.AppendURIPath()
+
+            HGLOBAL hGlobal;
+            int rc = createFileGroupDescriptor(mURIList, &hGlobal);
+            if (RT_SUCCESS(rc))
+            {
+                pMedium->tymed   = TYMED_HGLOBAL;
+                pMedium->hGlobal = hGlobal;
+
+                hr = S_OK;
+            }
+            break;
+        }
+
+        case FormatIndex_FileDescriptorW:
+            LogFlowFunc(("FormatIndex_FileDescriptorW\n"));
+            break;
+
+        case FormatIndex_FileContents:
+        {
+            LogFlowFunc(("FormatIndex_FileContents\n"));
+
+            hr = VBoxClipboardWinStreamImpl::Create(&mpStream);
+            if (SUCCEEDED(hr))
+            {
+                /* Hand over the stream to the caller. */
+                pMedium->tymed          = TYMED_ISTREAM;
+                pMedium->pstm           = mpStream;
+            }
+
+            break;
+        }
+
+        default:
+            break;
+    }
+
+    /* Error handling; at least return some basic data. */
+    if (FAILED(hr))
+    {
+        LogFunc(("Failed; copying medium ...\n"));
+
         pMedium->tymed          = pThisFormat->tymed;
         pMedium->pUnkForRelease = NULL;
-
-        /*
-         * URI list handling.
-         */
-        if (mstrFormat.equalsIgnoreCase("text/uri-list"))
-        {
-            int rc = VINF_SUCCESS;
-
-            RTCList<RTCString> lstFilesURI = RTCString((char*)mpvData, mcbData).split("\r\n");
-            RTCList<RTCString> lstFiles;
-            for (size_t i = 0; i < lstFilesURI.size(); i++)
-            {
-                char *pszFilePath = RTUriFilePath(lstFilesURI.at(i).c_str());
-                if (pszFilePath)
-                {
-                    lstFiles.append(pszFilePath);
-                    RTStrFree(pszFilePath);
-                }
-                else /* Unable to parse -- refuse entire request. */
-                {
-                    lstFiles.clear();
-                    rc = VERR_INVALID_PARAMETER;
-                    break;
-                }
-            }
-
-            size_t cFiles = lstFiles.size();
-            if (   RT_SUCCESS(rc)
-                && cFiles)
-            {
-#ifdef DEBUG
-                LogFlowFunc(("Files (%zu)\n", cFiles));
-                for (size_t i = 0; i < cFiles; i++)
-                    LogFlowFunc(("\tFile: %s\n", lstFiles.at(i).c_str()));
-#endif
-
-#if 0
-                if (   (pFormatEtc->tymed & TYMED_ISTREAM)
-                    && (pFormatEtc->dwAspect == DVASPECT_CONTENT)
-                    && (pFormatEtc->cfFormat == CF_FILECONTENTS))
-                {
-
-                }
-                else if  (   (pFormatEtc->tymed & TYMED_HGLOBAL)
-                          && (pFormatEtc->dwAspect == DVASPECT_CONTENT)
-                          && (pFormatEtc->cfFormat == CF_FILEDESCRIPTOR))
-                {
-
-                }
-                else if (   (pFormatEtc->tymed & TYMED_HGLOBAL)
-                         && (pFormatEtc->cfFormat == CF_PREFERREDDROPEFFECT))
-                {
-                    HGLOBAL hData = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE | GMEM_ZEROINIT, sizeof(DWORD));
-                    DWORD *pdwEffect = (DWORD *)GlobalLock(hData);
-                    AssertPtr(pdwEffect);
-                    *pdwEffect = DROPEFFECT_COPY;
-                    GlobalUnlock(hData);
-
-                    pMedium->hGlobal = hData;
-                    pMedium->tymed = TYMED_HGLOBAL;
-                }
-                else
-#endif
-                if (   (pFormatEtc->tymed & TYMED_HGLOBAL)
-                    && (pFormatEtc->dwAspect == DVASPECT_CONTENT)
-                    && (pFormatEtc->cfFormat == CF_TEXT))
-                {
-                    pMedium->hGlobal = GlobalAlloc(GHND, mcbData + 1);
-                    if (pMedium->hGlobal)
-                    {
-                        char *pcDst  = (char *)GlobalLock(pMedium->hGlobal);
-                        memcpy(pcDst, mpvData, mcbData);
-                        pcDst[mcbData] = '\0';
-                        GlobalUnlock(pMedium->hGlobal);
-
-                        hr = S_OK;
-                    }
-                }
-                else if (   (pFormatEtc->tymed & TYMED_HGLOBAL)
-                         && (pFormatEtc->dwAspect == DVASPECT_CONTENT)
-                         && (pFormatEtc->cfFormat == CF_HDROP))
-                {
-                    size_t cchFiles = 0; /* Number of ASCII characters. */
-                    for (size_t i = 0; i < cFiles; i++)
-                    {
-                        cchFiles += strlen(lstFiles.at(i).c_str());
-                        cchFiles += 1; /* Terminating '\0'. */
-                    }
-
-                    size_t cbBuf = sizeof(DROPFILES) + ((cchFiles + 1) * sizeof(RTUTF16));
-                    DROPFILES *pBuf = (DROPFILES *)RTMemAllocZ(cbBuf);
-                    if (pBuf)
-                    {
-                        pBuf->pFiles = sizeof(DROPFILES);
-                        pBuf->fWide = 1; /* We use unicode. Always. */
-
-                        uint8_t *pCurFile = (uint8_t *)pBuf + pBuf->pFiles;
-                        AssertPtr(pCurFile);
-
-                        for (size_t i = 0; i < cFiles && RT_SUCCESS(rc); i++)
-                        {
-                            size_t cchCurFile;
-                            PRTUTF16 pwszFile;
-                            rc = RTStrToUtf16(lstFiles.at(i).c_str(), &pwszFile);
-                            if (RT_SUCCESS(rc))
-                            {
-                                cchCurFile = RTUtf16Len(pwszFile);
-                                Assert(cchCurFile);
-                                memcpy(pCurFile, pwszFile, cchCurFile * sizeof(RTUTF16));
-                                RTUtf16Free(pwszFile);
-                            }
-                            else
-                                break;
-
-                            pCurFile += cchCurFile * sizeof(RTUTF16);
-
-                            /* Terminate current file name. */
-                            *pCurFile = L'\0';
-                            pCurFile += sizeof(RTUTF16);
-                        }
-
-                        if (RT_SUCCESS(rc))
-                        {
-                            *pCurFile = L'\0'; /* Final list terminator. */
-
-                            pMedium->tymed = TYMED_HGLOBAL;
-                            pMedium->pUnkForRelease = NULL;
-                            pMedium->hGlobal = GlobalAlloc(  GMEM_ZEROINIT
-                                                           | GMEM_MOVEABLE
-                                                           | GMEM_DDESHARE, cbBuf);
-                            if (pMedium->hGlobal)
-                            {
-                                LPVOID pMem = GlobalLock(pMedium->hGlobal);
-                                if (pMem)
-                                {
-                                    memcpy(pMem, pBuf, cbBuf);
-                                    GlobalUnlock(pMedium->hGlobal);
-
-                                    hr = S_OK;
-                                }
-                            }
-                        }
-
-                        RTMemFree(pBuf);
-                    }
-                    else
-                        rc = VERR_NO_MEMORY;
-                }
-            }
-
-            if (RT_FAILURE(rc))
-                hr = DV_E_FORMATETC;
-        }
-        /*
-         * Plain text handling.
-         */
-        else if (   mstrFormat.equalsIgnoreCase("text/plain")
-                 || mstrFormat.equalsIgnoreCase("text/html")
-                 || mstrFormat.equalsIgnoreCase("text/plain;charset=utf-8")
-                 || mstrFormat.equalsIgnoreCase("text/plain;charset=utf-16")
-                 || mstrFormat.equalsIgnoreCase("text/richtext")
-                 || mstrFormat.equalsIgnoreCase("UTF8_STRING")
-                 || mstrFormat.equalsIgnoreCase("TEXT")
-                 || mstrFormat.equalsIgnoreCase("STRING"))
-        {
-            pMedium->hGlobal = GlobalAlloc(GHND, mcbData + 1);
-            if (pMedium->hGlobal)
-            {
-                char *pcDst  = (char *)GlobalLock(pMedium->hGlobal);
-                memcpy(pcDst, mpvData, mcbData);
-                pcDst[mcbData] = '\0';
-                GlobalUnlock(pMedium->hGlobal);
-
-                hr = S_OK;
-            }
-        }
-        else
-            LogRel(("Clipboard: Error: Format '%s' not implemented\n", mstrFormat.c_str()));
-    }
-
-    /* Error handling; at least return some basic data. */
-    if (FAILED(hr))
-    {
-        LogFlowFunc(("Copying medium ...\n"));
-        switch (pThisMedium->tymed)
-        {
-
-        case TYMED_HGLOBAL:
-            pMedium->hGlobal = (HGLOBAL)OleDuplicateData(pThisMedium->hGlobal,
-                                                         pThisFormat->cfFormat, NULL);
-            break;
-
-        default:
-            break;
-        }
-
-        pMedium->tymed          = pThisFormat->tymed;
-        pMedium->pUnkForRelease = NULL;
     }
 
     if (hr == DV_E_FORMATETC)
-        LogRel(("Clipboard: Error handling format '%s' (%RU32 bytes)\n", mstrFormat.c_str(), mcbData));
+        LogRel(("Clipboard: Error handling format\n"));
 
     LogFlowFunc(("hr=%Rhrc\n", hr));
@@ -437,5 +370,5 @@
     RT_NOREF(pFormatEtc, pMedium);
     LogFlowFunc(("\n"));
-    return DATA_E_FORMATETC;
+    return E_NOTIMPL;
 }
 
@@ -450,5 +383,5 @@
 {
     LogFlowFunc(("\n"));
-    return (LookupFormatEtc(pFormatEtc, NULL /* puIndex */)) ? S_OK : DV_E_FORMATETC;
+    return (lookupFormatEtc(pFormatEtc, NULL /* puIndex */)) ? S_OK : DV_E_FORMATETC;
 }
 
@@ -466,4 +399,6 @@
 {
     RT_NOREF(pFormatEtc, pMedium, fRelease);
+    LogFlowFunc(("\n"));
+
     return E_NOTIMPL;
 }
@@ -501,13 +436,50 @@
 }
 
+#ifdef VBOX_WITH_SHARED_CLIPBOARD_WIN_ASYNC
+/*
+ * IDataObjectAsyncCapability methods.
+ */
+
+STDMETHODIMP VBoxClipboardWinDataObject::EndOperation(HRESULT hResult, IBindCtx* pbcReserved, DWORD dwEffects)
+{
+     RT_NOREF(hResult, pbcReserved, dwEffects);
+     return E_NOTIMPL;
+}
+
+STDMETHODIMP VBoxClipboardWinDataObject::GetAsyncMode(BOOL* pfIsOpAsync)
+{
+     RT_NOREF(pfIsOpAsync);
+     return E_NOTIMPL;
+}
+
+STDMETHODIMP VBoxClipboardWinDataObject::InOperation(BOOL* pfInAsyncOp)
+{
+     RT_NOREF(pfInAsyncOp);
+     return E_NOTIMPL;
+}
+
+STDMETHODIMP VBoxClipboardWinDataObject::SetAsyncMode(BOOL fDoOpAsync)
+{
+     RT_NOREF(fDoOpAsync);
+     return E_NOTIMPL;
+}
+
+STDMETHODIMP VBoxClipboardWinDataObject::StartOperation(IBindCtx* pbcReserved)
+{
+     RT_NOREF(pbcReserved);
+     return E_NOTIMPL;
+}
+#endif /* VBOX_WITH_SHARED_CLIPBOARD_WIN_ASYNC */
+
 /*
  * Own stuff.
  */
 
-int VBoxClipboardWinDataObject::Abort(void)
-{
-    LogFlowFunc(("Aborting ...\n"));
-    mStatus = Aborted;
-    return RTSemEventSignal(mEventDropped);
+int VBoxClipboardWinDataObject::Init(uint32_t idClient)
+{
+    muClientID = idClient;
+
+    LogFlowFuncLeaveRC(VINF_SUCCESS);
+    return VINF_SUCCESS;
 }
 
@@ -595,5 +567,5 @@
 }
 
-bool VBoxClipboardWinDataObject::LookupFormatEtc(LPFORMATETC pFormatEtc, ULONG *puIndex)
+bool VBoxClipboardWinDataObject::lookupFormatEtc(LPFORMATETC pFormatEtc, ULONG *puIndex)
 {
     AssertReturn(pFormatEtc, false);
@@ -622,26 +594,7 @@
 }
 
-/* static */
-HGLOBAL VBoxClipboardWinDataObject::MemDup(HGLOBAL hMemSource)
-{
-    DWORD dwLen    = GlobalSize(hMemSource);
-    AssertReturn(dwLen, NULL);
-    PVOID pvSource = GlobalLock(hMemSource);
-    if (pvSource)
-    {
-        PVOID pvDest = GlobalAlloc(GMEM_FIXED, dwLen);
-        if (pvDest)
-            memcpy(pvDest, pvSource, dwLen);
-
-        GlobalUnlock(hMemSource);
-        return pvDest;
-    }
-
-    return NULL;
-}
-
-void VBoxClipboardWinDataObject::RegisterFormat(LPFORMATETC pFormatEtc, CLIPFORMAT clipFormat,
-                                       TYMED tyMed, LONG lIndex, DWORD dwAspect,
-                                       DVTARGETDEVICE *pTargetDevice)
+void VBoxClipboardWinDataObject::registerFormat(LPFORMATETC pFormatEtc, CLIPFORMAT clipFormat,
+                                                TYMED tyMed, LONG lIndex, DWORD dwAspect,
+                                                DVTARGETDEVICE *pTargetDevice)
 {
     AssertPtr(pFormatEtc);
@@ -657,49 +610,2 @@
 }
 
-void VBoxClipboardWinDataObject::SetStatus(Status status)
-{
-    LogFlowFunc(("Setting status to %ld\n", status));
-    mStatus = status;
-}
-
-int VBoxClipboardWinDataObject::Signal(const RTCString &strFormat,
-                              const void *pvData, uint32_t cbData)
-{
-    int rc;
-
-    if (cbData)
-    {
-        mpvData = RTMemAlloc(cbData);
-        if (mpvData)
-        {
-            memcpy(mpvData, pvData, cbData);
-            mcbData = cbData;
-            rc = VINF_SUCCESS;
-        }
-        else
-            rc = VERR_NO_MEMORY;
-    }
-    else
-        rc = VINF_SUCCESS;
-
-    if (RT_SUCCESS(rc))
-    {
-        mStatus    = Dropped;
-        mstrFormat = strFormat;
-    }
-    else
-    {
-        mStatus = Aborted;
-    }
-
-    /* Signal in any case. */
-    LogRel2(("Clipboard: Signalling drop event\n"));
-
-    int rc2 = RTSemEventSignal(mEventDropped);
-    if (RT_SUCCESS(rc))
-        rc = rc2;
-
-    LogFunc(("mStatus=%RU32, rc=%Rrc\n", mStatus, rc));
-    return rc;
-}
-
Index: /trunk/src/VBox/GuestHost/SharedClipboard/ClipboardStreamImpl-win.cpp
===================================================================
--- /trunk/src/VBox/GuestHost/SharedClipboard/ClipboardStreamImpl-win.cpp	(revision 78473)
+++ /trunk/src/VBox/GuestHost/SharedClipboard/ClipboardStreamImpl-win.cpp	(revision 78474)
@@ -25,4 +25,5 @@
 #include <iprt/asm.h>
 #include <iprt/ldr.h>
+#include <iprt/thread.h>
 
 #include <VBox/GuestHost/SharedClipboard.h>
@@ -43,2 +44,185 @@
 *********************************************************************************************************************************/
 
+
+
+VBoxClipboardWinStreamImpl::VBoxClipboardWinStreamImpl(void)
+    : m_lRefCount(1)
+{
+
+}
+
+VBoxClipboardWinStreamImpl::~VBoxClipboardWinStreamImpl(void)
+{
+}
+
+/*
+ * IUnknown methods.
+ */
+
+STDMETHODIMP VBoxClipboardWinStreamImpl::QueryInterface(REFIID iid, void ** ppvObject)
+{
+    AssertPtrReturn(ppvObject, E_INVALIDARG);
+
+    if (   iid == IID_IStream
+        || iid == IID_IUnknown)
+    {
+        AddRef();
+        *ppvObject = this;
+        return S_OK;
+    }
+
+    *ppvObject = 0;
+    return E_NOINTERFACE;
+}
+
+STDMETHODIMP_(ULONG) VBoxClipboardWinStreamImpl::AddRef(void)
+{
+    LONG lCount = InterlockedIncrement(&m_lRefCount);
+    LogFlowFunc(("lCount=%RI32\n", lCount));
+    return lCount;
+}
+
+STDMETHODIMP_(ULONG) VBoxClipboardWinStreamImpl::Release(void)
+{
+    LONG lCount = InterlockedDecrement(&m_lRefCount);
+    LogFlowFunc(("lCount=%RI32\n", m_lRefCount));
+    if (lCount == 0)
+    {
+        delete this;
+        return 0;
+    }
+
+    return lCount;
+}
+
+/*
+ * IStream methods.
+ */
+
+STDMETHODIMP VBoxClipboardWinStreamImpl::Clone(IStream** ppStream)
+{
+    RT_NOREF(ppStream);
+
+    LogFlowFuncEnter();
+    return E_NOTIMPL;
+}
+
+STDMETHODIMP VBoxClipboardWinStreamImpl::Commit(DWORD dwFrags)
+{
+    RT_NOREF(dwFrags);
+
+    LogFlowFuncEnter();
+    return E_NOTIMPL;
+}
+
+STDMETHODIMP VBoxClipboardWinStreamImpl::CopyTo(IStream* pDestStream, ULARGE_INTEGER nBytesToCopy, ULARGE_INTEGER* nBytesRead,
+                                                ULARGE_INTEGER* nBytesWritten)
+{
+    RT_NOREF(pDestStream, nBytesToCopy, nBytesRead, nBytesWritten);
+
+    LogFlowFuncEnter();
+    return E_NOTIMPL;
+}
+
+STDMETHODIMP VBoxClipboardWinStreamImpl::LockRegion(ULARGE_INTEGER nStart, ULARGE_INTEGER nBytes,DWORD dwFlags)
+{
+    RT_NOREF(nStart, nBytes, dwFlags);
+
+    LogFlowFuncEnter();
+    return E_NOTIMPL;
+}
+
+static ULONG cbFileSize = _1M;
+static ULONG cbSizeRead = 0;
+
+STDMETHODIMP VBoxClipboardWinStreamImpl::Read(void* pvBuffer, ULONG nBytesToRead, ULONG* nBytesRead)
+{
+    /* If the file size is 0, already return at least 1 byte, else the whole operation will fail. */
+
+    ULONG cbToRead = RT_MIN(cbFileSize - cbSizeRead,  _4K /* nBytesToRead */);
+
+    if (cbToRead > nBytesToRead)
+        cbToRead = nBytesToRead;
+
+    LogFlowFunc(("pvBuffer=%p, nBytesToRead=%u -> cbSizeRead=%u, cbToRead=%u\n", pvBuffer, nBytesToRead, cbSizeRead, cbToRead));
+
+    if (cbToRead)
+    {
+        memset(pvBuffer, cbToRead, 0x65);
+        cbSizeRead += cbToRead;
+    }
+
+    if (nBytesRead)
+        *nBytesRead = cbToRead;
+
+    if (cbSizeRead == cbFileSize)
+        cbSizeRead = 0;
+
+    return S_OK;
+}
+
+STDMETHODIMP VBoxClipboardWinStreamImpl::Revert(void)
+{
+    LogFlowFuncEnter();
+    return E_NOTIMPL;
+}
+
+STDMETHODIMP VBoxClipboardWinStreamImpl::Seek(LARGE_INTEGER nMove, DWORD dwOrigin, ULARGE_INTEGER* nNewPos)
+{
+    RT_NOREF(nMove, dwOrigin, nNewPos);
+
+    LogFlowFuncEnter();
+    return E_NOTIMPL;
+}
+
+STDMETHODIMP VBoxClipboardWinStreamImpl::SetSize(ULARGE_INTEGER nNewSize)
+{
+    RT_NOREF(nNewSize);
+
+    LogFlowFuncEnter();
+    return E_NOTIMPL;
+}
+
+STDMETHODIMP VBoxClipboardWinStreamImpl::Stat(STATSTG* statstg, DWORD dwFlags)
+{
+    RT_NOREF(statstg, dwFlags);
+
+    LogFlowFuncEnter();
+    return E_NOTIMPL;
+}
+
+STDMETHODIMP VBoxClipboardWinStreamImpl::UnlockRegion(ULARGE_INTEGER nStart, ULARGE_INTEGER nBytes, DWORD dwFlags)
+{
+    RT_NOREF(nStart, nBytes, dwFlags);
+
+    LogFlowFuncEnter();
+    return E_NOTIMPL;
+}
+
+STDMETHODIMP VBoxClipboardWinStreamImpl::Write(const void* pvBuffer, ULONG nBytesToRead, ULONG* nBytesRead)
+{
+    RT_NOREF(pvBuffer, nBytesToRead, nBytesRead);
+
+    LogFlowFuncEnter();
+    return E_NOTIMPL;
+}
+
+/*
+ * Own stuff.
+ */
+
+/* static */
+HRESULT VBoxClipboardWinStreamImpl::Create(IStream **ppStream)
+{
+    VBoxClipboardWinStreamImpl *pStream = new VBoxClipboardWinStreamImpl();
+    if (pStream)
+    {
+        pStream->AddRef();
+
+        *ppStream = pStream;
+        return S_OK;
+    }
+
+    return E_FAIL;
+}
+
Index: /trunk/src/VBox/GuestHost/SharedClipboard/clipboard-win.cpp
===================================================================
--- /trunk/src/VBox/GuestHost/SharedClipboard/clipboard-win.cpp	(revision 78473)
+++ /trunk/src/VBox/GuestHost/SharedClipboard/clipboard-win.cpp	(revision 78474)
@@ -87,9 +87,15 @@
     int rc;
 
+    LogFlowFuncEnter();
+
     const BOOL fRc = CloseClipboard();
     if (RT_UNLIKELY(!fRc))
     {
         const DWORD dwLastErr = GetLastError();
-        rc = RTErrConvertFromWin32(dwLastErr);
+        if (dwLastErr == ERROR_CLIPBOARD_NOT_OPEN)
+            rc = VERR_INVALID_STATE;
+        else
+            rc = RTErrConvertFromWin32(dwLastErr);
+
         LogFunc(("Failed with %Rrc (0x%x)\n", rc, dwLastErr));
     }
@@ -108,4 +114,6 @@
 {
     int rc;
+
+    LogFlowFuncEnter();
 
     const BOOL fRc = EmptyClipboard();
@@ -113,5 +121,9 @@
     {
         const DWORD dwLastErr = GetLastError();
-        rc = RTErrConvertFromWin32(dwLastErr);
+        if (dwLastErr == ERROR_CLIPBOARD_NOT_OPEN)
+            rc = VERR_INVALID_STATE;
+        else
+            rc = RTErrConvertFromWin32(dwLastErr);
+
         LogFunc(("Failed with %Rrc (0x%x)\n", rc, dwLastErr));
     }
@@ -265,4 +277,42 @@
 }
 
+VBOXCLIPBOARDFORMAT VBoxClipboardWinClipboardFormatToVBox(UINT uFormat)
+{
+    /* Insert the requested clipboard format data into the clipboard. */
+    VBOXCLIPBOARDFORMAT vboxFormat = VBOX_SHARED_CLIPBOARD_FMT_NONE;
+
+    switch (uFormat)
+    {
+      case CF_UNICODETEXT:
+          vboxFormat = VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT;
+          break;
+
+      case CF_DIB:
+          vboxFormat = VBOX_SHARED_CLIPBOARD_FMT_BITMAP;
+          break;
+
+      default:
+          if (uFormat >= 0xC000) /** Formats registered with RegisterClipboardFormat() start at this index. */
+          {
+              TCHAR szFormatName[256]; /** @todo r=andy Do we need Unicode support here as well? */
+              int cActual = GetClipboardFormatName(uFormat, szFormatName, sizeof(szFormatName) / sizeof(TCHAR));
+              if (cActual)
+              {
+                  LogFunc(("szFormatName=%s\n", szFormatName));
+
+                  if (RTStrCmp(szFormatName, VBOX_CLIPBOARD_WIN_REGFMT_HTML) == 0)
+                      vboxFormat = VBOX_SHARED_CLIPBOARD_FMT_HTML;
+#ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
+                  else if (RTStrCmp(szFormatName, VBOX_CLIPBOARD_WIN_REGFMT_URI_LIST) == 0)
+                      vboxFormat = VBOX_SHARED_CLIPBOARD_FMT_URI_LIST;
+#endif
+              }
+          }
+          break;
+    }
+
+    return vboxFormat;
+}
+
 /**
  * Retrieves all supported clipboard formats of a specific clipboard.
@@ -270,12 +320,12 @@
  * @returns VBox status code.
  * @param   pCtx                Windows clipboard context to retrieve formats for.
- * @param   puFormats           Where to store the retrieved formats of type VBOX_SHARED_CLIPBOARD_FMT_ (bitmask).
- */
-int VBoxClipboardWinGetFormats(PVBOXCLIPBOARDWINCTX pCtx, uint32_t *puFormats)
+ * @param   pfFormats           Where to store the retrieved formats of type VBOX_SHARED_CLIPBOARD_FMT_ (bitmask).
+ */
+int VBoxClipboardWinGetFormats(PVBOXCLIPBOARDWINCTX pCtx, PVBOXCLIPBOARDFORMATS pfFormats)
 {
     AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
-    AssertPtrReturn(puFormats, VERR_INVALID_POINTER);
-
-    uint32_t uFormats = VBOX_SHARED_CLIPBOARD_FMT_NONE;
+    AssertPtrReturn(pfFormats, VERR_INVALID_POINTER);
+
+    VBOXCLIPBOARDFORMATS fFormats = VBOX_SHARED_CLIPBOARD_FMT_NONE;
 
     /* Query list of available formats and report to host. */
@@ -283,43 +333,7 @@
     if (RT_SUCCESS(rc))
     {
-        UINT uCurFormat = 0;
+        UINT uCurFormat = 0; /* Must be set to zero for EnumClipboardFormats(). */
         while ((uCurFormat = EnumClipboardFormats(uCurFormat)) != 0)
-        {
-            LogFlowFunc(("uFormat = 0x%08X\n", uCurFormat));
-            switch (uCurFormat)
-            {
-                case CF_UNICODETEXT:
-                case CF_TEXT:
-                    uFormats |= VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT;
-                    break;
-
-                case CF_DIB:
-                case CF_BITMAP:
-                    uFormats |= VBOX_SHARED_CLIPBOARD_FMT_BITMAP;
-                    break;
-
-#ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
-                case CF_HDROP:
-                    uFormats |= VBOX_SHARED_CLIPBOARD_FMT_URI_LIST;
-                    break;
-#endif
-                default:
-                {
-                    if (uCurFormat >= 0xC000) /** @todo r=andy Find a define for this. */
-                    {
-                        TCHAR szFormatName[256]; /** @todo r=andy Is this enough? */
-                        int cActual = GetClipboardFormatName(uCurFormat, szFormatName, sizeof(szFormatName)/sizeof (TCHAR));
-                        if (cActual)
-                        {
-                            if (strcmp (szFormatName, "HTML Format") == 0)
-                            {
-                                uFormats |= VBOX_SHARED_CLIPBOARD_FMT_HTML;
-                            }
-                        }
-                    }
-                    break;
-                }
-            }
-        }
+            fFormats |= VBoxClipboardWinClipboardFormatToVBox(uCurFormat);
 
         int rc2 = VBoxClipboardWinClose();
@@ -333,9 +347,9 @@
     else
     {
-        LogFlowFunc(("uFormats = 0x%08X\n", uFormats));
-        *puFormats = uFormats;
-    }
-
-    return rc;
-}
-
+        LogFlowFunc(("pfFormats=0x%08X\n", pfFormats));
+        *pfFormats = fFormats;
+    }
+
+    return rc;
+}
+
