Index: /trunk/include/VBox/GuestHost/SharedClipboard-uri.h
===================================================================
--- /trunk/include/VBox/GuestHost/SharedClipboard-uri.h	(revision 78500)
+++ /trunk/include/VBox/GuestHost/SharedClipboard-uri.h	(revision 78501)
@@ -32,4 +32,5 @@
 
 #include <iprt/assert.h>
+#include <iprt/critsect.h>
 #include <iprt/fs.h>
 
@@ -37,28 +38,34 @@
 #include <iprt/cpp/ministring.h>
 
-/** SharedClipboardDroppedFiles flags. */
-typedef uint32_t SHAREDCLIPBOARDDROPPEDFILEFLAGS;
+/** SharedClipboardCache flags. */
+typedef uint32_t SHAREDCLIPBOARDCACHEFLAGS;
 
 /** No flags specified. */
-#define SHAREDCLIPBOARDDROPPEDFILE_FLAGS_NONE                   0
+#define SHAREDCLIPBOARDCACHE_FLAGS_NONE     0
 
 /**
- * Class for maintaining a "dropped files" directory
+ * Class for maintaining a Shared Clipboard cache
  * on the host or guest. This will contain all received files & directories
- * for a single Shared Clipboard "paste" operation.
+ * for a single Shared Clipboard operation.
  *
  * In case of a failed Shared Clipboard operation this class can also
  * perform a gentle rollback if required.
  */
-class SharedClipboardDroppedFiles
+class SharedClipboardCache
 {
 
 public:
 
-    SharedClipboardDroppedFiles(void);
-    SharedClipboardDroppedFiles(const char *pszPath, SHAREDCLIPBOARDDROPPEDFILEFLAGS fFlags = SHAREDCLIPBOARDDROPPEDFILE_FLAGS_NONE);
-    virtual ~SharedClipboardDroppedFiles(void);
-
-public:
+    SharedClipboardCache(void);
+    SharedClipboardCache(const char *pszPath, SHAREDCLIPBOARDCACHEFLAGS fFlags = SHAREDCLIPBOARDCACHE_FLAGS_NONE);
+    virtual ~SharedClipboardCache(void);
+
+public:
+
+    uint16_t AddRef(void);
+    uint16_t Release(void);
+
+    int Lock(void);
+    int Unlock(void);
 
     int AddFile(const char *pszFile);
@@ -66,6 +73,6 @@
     int Close(void);
     bool IsOpen(void) const;
-    int OpenEx(const char *pszPath, SHAREDCLIPBOARDDROPPEDFILEFLAGS fFlags = SHAREDCLIPBOARDDROPPEDFILE_FLAGS_NONE);
-    int OpenTemp(SHAREDCLIPBOARDDROPPEDFILEFLAGS fFlags = SHAREDCLIPBOARDDROPPEDFILE_FLAGS_NONE);
+    int OpenEx(const char *pszPath, SHAREDCLIPBOARDCACHEFLAGS fFlags = SHAREDCLIPBOARDCACHE_FLAGS_NONE);
+    int OpenTemp(SHAREDCLIPBOARDCACHEFLAGS fFlags = SHAREDCLIPBOARDCACHE_FLAGS_NONE);
     const char *GetDirAbs(void) const;
     int Reopen(void);
@@ -75,8 +82,14 @@
 protected:
 
+    int initInternal(void);
+    int destroyInternal(void);
     int closeInternal(void);
 
 protected:
 
+    /** Number of references to this instance. */
+    volatile uint16_t            m_cRefs;
+    /** Critical section for serializing access. */
+    RTCRITSECT                   m_CritSect;
     /** Open flags. */
     uint32_t                     m_fOpen;
@@ -91,5 +104,5 @@
 };
 
-int SharedClipboardSanitizeFilename(char *pszPath, size_t cbPath);
+int SharedClipboardPathSanitizeFilename(char *pszPath, size_t cbPath);
 int SharedClipboardPathSanitize(char *pszPath, size_t cbPath);
 
Index: /trunk/include/VBox/GuestHost/SharedClipboard-win.h
===================================================================
--- /trunk/include/VBox/GuestHost/SharedClipboard-win.h	(revision 78500)
+++ /trunk/include/VBox/GuestHost/SharedClipboard-win.h	(revision 78501)
@@ -37,4 +37,5 @@
 # ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
 #  include <iprt/cpp/ministring.h> /* For RTCString. */
+#  include <iprt/win/shlobj.h> /* For DROPFILES and friends. */
 #  include <oleidl.h>
 # endif
@@ -49,7 +50,4 @@
  *       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. */
@@ -127,10 +125,22 @@
 int VBoxClipboardWinRemoveFromCBChain(PVBOXCLIPBOARDWINCTX pCtx);
 VOID CALLBACK VBoxClipboardWinChainPingProc(HWND hWnd, UINT uMsg, ULONG_PTR dwData, LRESULT lResult);
+
 VBOXCLIPBOARDFORMAT VBoxClipboardWinClipboardFormatToVBox(UINT uFormat);
 int VBoxClipboardWinGetFormats(PVBOXCLIPBOARDWINCTX pCtx, PVBOXCLIPBOARDFORMAT pfFormats);
 
+#ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
+int VBoxClipboardWinDropFilesToStringList(DROPFILES *pDropFiles, void **ppvData, size_t *pcbData);
+#endif
+
+int VBoxClipboardWinGetCFHTMLHeaderValue(const char *pszSrc, const char *pszOption, uint32_t *puValue);
+bool VBoxClipboardWinIsCFHTML(const char *pszSource);
+int VBoxClipboardWinConvertCFHTMLToMIME(const char *pszSource, const uint32_t cch, char **ppszOutput, uint32_t *pcbOutput);
+int VBoxClipboardWinConvertMIMEToCFHTML(const char *pszSource, size_t cb, char **ppszOutput, uint32_t *pcbOutput);
+
 # ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
 class SharedClipboardURIList;
+#  ifndef FILEGROUPDESCRIPTOR
 class FILEGROUPDESCRIPTOR;
+#  endif
 
 class VBoxClipboardWinDataObject : public IDataObject //, public IDataObjectAsyncCapability
Index: /trunk/src/VBox/Additions/WINNT/VBoxTray/Makefile.kmk
===================================================================
--- /trunk/src/VBox/Additions/WINNT/VBoxTray/Makefile.kmk	(revision 78500)
+++ /trunk/src/VBox/Additions/WINNT/VBoxTray/Makefile.kmk	(revision 78501)
@@ -56,10 +56,11 @@
  ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
  VBoxTray_SOURCES  += \
-	$(PATH_ROOT)/src/VBox/GuestHost/SharedClipboard/ClipboardURIList.cpp \
-	$(PATH_ROOT)/src/VBox/GuestHost/SharedClipboard/ClipboardURIObject.cpp \
-	$(PATH_ROOT)/src/VBox/GuestHost/SharedClipboard/ClipboardPath.cpp \
+ 	$(PATH_ROOT)/src/VBox/GuestHost/SharedClipboard/ClipboardCache.cpp \
 	$(PATH_ROOT)/src/VBox/GuestHost/SharedClipboard/ClipboardDataObjectImpl-win.cpp \
 	$(PATH_ROOT)/src/VBox/GuestHost/SharedClipboard/ClipboardEnumFormatEtcImpl-win.cpp \
-	$(PATH_ROOT)/src/VBox/GuestHost/SharedClipboard/ClipboardStreamImpl-win.cpp
+	$(PATH_ROOT)/src/VBox/GuestHost/SharedClipboard/ClipboardPath.cpp \
+	$(PATH_ROOT)/src/VBox/GuestHost/SharedClipboard/ClipboardStreamImpl-win.cpp \
+	$(PATH_ROOT)/src/VBox/GuestHost/SharedClipboard/ClipboardURIList.cpp \
+	$(PATH_ROOT)/src/VBox/GuestHost/SharedClipboard/ClipboardURIObject.cpp
  endif
 endif
Index: /trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxClipboard.cpp
===================================================================
--- /trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxClipboard.cpp	(revision 78500)
+++ /trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxClipboard.cpp	(revision 78501)
@@ -79,5 +79,5 @@
     const PVBOXCLIPBOARDWINCTX pWinCtx = &pCtx->Win;
 
-    LRESULT rc = 0;
+    LRESULT lresultRc = 0;
 
     switch (msg)
@@ -87,12 +87,15 @@
            if (GetClipboardOwner() != hwnd)
            {
-               Log(("WM_CLIPBOARDUPDATE\n"));
-
-               /* Clipboard was updated by another application. */
+               /* Clipboard was updated by another application.
+                * Report available formats to the host. */
                VBOXCLIPBOARDFORMATS fFormats;
-               int vboxrc = VBoxClipboardWinGetFormats(&pCtx->Win, &fFormats);
-               if (RT_SUCCESS(vboxrc))
-                   vboxrc = VbglR3ClipboardReportFormats(pCtx->u32ClientID, fFormats);
+               int rc = VBoxClipboardWinGetFormats(&pCtx->Win, &fFormats);
+               if (RT_SUCCESS(rc))
+                   rc = VbglR3ClipboardReportFormats(pCtx->u32ClientID, fFormats);
+
+               LogFunc(("WM_CLIPBOARDUPDATE: rc=%Rrc, fFormats=0x%x\n", rc, fFormats));
            }
+           else
+               LogFlowFunc(("WM_CLIPBOARDUPDATE: No change (VBoxTray is owner)\n"));
         }
         break;
@@ -102,5 +105,5 @@
            if (VBoxClipboardWinIsNewAPI(&pWinCtx->newAPI))
            {
-               rc = DefWindowProc(hwnd, msg, wParam, lParam);
+               lresultRc = DefWindowProc(hwnd, msg, wParam, lParam);
                break;
            }
@@ -123,8 +126,8 @@
                    /* Pass the message further. */
                    DWORD_PTR dwResult;
-                   rc = SendMessageTimeout(pWinCtx->hWndNextInChain, WM_CHANGECBCHAIN, wParam, lParam, 0,
-                                           VBOX_CLIPBOARD_CBCHAIN_TIMEOUT_MS, &dwResult);
-                   if (!rc)
-                       rc = (LRESULT)dwResult;
+                   lresultRc = SendMessageTimeout(pWinCtx->hWndNextInChain, WM_CHANGECBCHAIN, wParam, lParam, 0,
+                                                  VBOX_CLIPBOARD_CBCHAIN_TIMEOUT_MS, &dwResult);
+                   if (!lresultRc)
+                       lresultRc = (LRESULT)dwResult;
                }
            }
@@ -141,7 +144,7 @@
                /* WM_DRAWCLIPBOARD always expects a return code of 0, so don't change "rc" here. */
                VBOXCLIPBOARDFORMATS fFormats;
-               int vboxrc = VBoxClipboardWinGetFormats(pWinCtx, &fFormats);
-               if (RT_SUCCESS(vboxrc))
-                   vboxrc = VbglR3ClipboardReportFormats(pCtx->u32ClientID, fFormats);
+               int rc = VBoxClipboardWinGetFormats(pWinCtx, &fFormats);
+               if (RT_SUCCESS(rc))
+                   rc = VbglR3ClipboardReportFormats(pCtx->u32ClientID, fFormats);
             }
 
@@ -197,5 +200,10 @@
             LogFunc(("WM_RENDERFORMAT: cfFormat=%u -> fFormat=0x%x\n", cfFormat, fFormat));
 
-            if (fFormat != VBOX_SHARED_CLIPBOARD_FMT_NONE)
+            if (fFormat == VBOX_SHARED_CLIPBOARD_FMT_NONE)
+            {
+                LogFunc(("WM_RENDERFORMAT: Unsupported format requested\n"));
+                VBoxClipboardWinClear();
+            }
+            else
             {
                 const uint32_t cbPrealloc = _4K;
@@ -214,8 +222,8 @@
                     {
                         /* 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))
+                        int rc = VbglR3ClipboardReadData(pCtx->u32ClientID, fFormat, pMem, cbPrealloc, &cb);
+                        LogFlowFunc(("VbglR3ClipboardReadData returned with rc = %Rrc\n",  rc));
+
+                        if (RT_SUCCESS(rc))
                         {
                             if (cb == 0)
@@ -245,9 +253,9 @@
                                         /* Read the host data to the preallocated buffer. */
                                         uint32_t cbNew = 0;
-                                        vboxrc = VbglR3ClipboardReadData(pCtx->u32ClientID, fFormat, pMem, cb, &cbNew);
+                                        rc = 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)
+                                                     rc, cb, cbNew));
+
+                                        if (RT_SUCCESS(rc)
                                             && cbNew <= cb)
                                         {
@@ -335,6 +343,6 @@
             * windows is to be destroyed and therefore the guest side becomes inactive.
             */
-            int vboxrc = VBoxClipboardWinOpen(hwnd);
-            if (RT_SUCCESS(vboxrc))
+            int rc = VBoxClipboardWinOpen(hwnd);
+            if (RT_SUCCESS(rc))
             {
                VBoxClipboardWinClear();
@@ -351,6 +359,6 @@
            LogFunc(("VBOX_WM_SHCLPB_SET_FORMATS: fFormats=0x%x\n", fFormats));
 
-           int vboxrc = VBoxClipboardWinOpen(hwnd);
-           if (RT_SUCCESS(vboxrc))
+           int rc = VBoxClipboardWinOpen(hwnd);
+           if (RT_SUCCESS(rc))
            {
                VBoxClipboardWinClear();
@@ -366,5 +374,4 @@
                    hClip = SetClipboardData(CF_UNICODETEXT, NULL);
                }
-
                else if (fFormats & VBOX_SHARED_CLIPBOARD_FMT_BITMAP)
                {
@@ -372,5 +379,4 @@
                    hClip = SetClipboardData(CF_DIB, NULL);
                }
-
                else if (fFormats & VBOX_SHARED_CLIPBOARD_FMT_HTML)
                {
@@ -380,5 +386,4 @@
                        hClip = SetClipboardData(cfFormat, NULL);
                }
-
 #ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
                else if (fFormats & VBOX_SHARED_CLIPBOARD_FMT_URI_LIST)
@@ -390,6 +395,6 @@
                        if (pWinCtx->URI.pDataObj)
                        {
-                           int vboxrc = pWinCtx->URI.pDataObj->Init(pCtx->u32ClientID);
-                           if (RT_SUCCESS(vboxrc))
+                           rc = pWinCtx->URI.pDataObj->Init(pCtx->u32ClientID);
+                           if (RT_SUCCESS(rc))
                            {
                                VBoxClipboardWinClose();
@@ -429,11 +434,10 @@
             LogFlowFunc(("VBOX_WM_SHCLPB_READ_DATA: u32Formats=0x%x\n", u32Formats));
 
-            int vboxrc = VBoxClipboardWinOpen(hwnd);
-            if (RT_SUCCESS(vboxrc))
+            int rc = VBoxClipboardWinOpen(hwnd);
+            if (RT_SUCCESS(rc))
             {
                if (u32Formats & VBOX_SHARED_CLIPBOARD_FMT_BITMAP)
                {
                    hClip = GetClipboardData(CF_DIB);
-
                    if (hClip != NULL)
                    {
@@ -441,6 +445,6 @@
                        if (lp != NULL)
                        {
-                           vboxrc = VbglR3ClipboardWriteData(pCtx->u32ClientID, VBOX_SHARED_CLIPBOARD_FMT_BITMAP,
-                                                             lp, GlobalSize(hClip));
+                           rc = VbglR3ClipboardWriteData(pCtx->u32ClientID, VBOX_SHARED_CLIPBOARD_FMT_BITMAP,
+                                                         lp, GlobalSize(hClip));
                            GlobalUnlock(hClip);
                        }
@@ -454,13 +458,11 @@
                {
                    hClip = GetClipboardData(CF_UNICODETEXT);
-
                    if (hClip != NULL)
                    {
                        LPWSTR uniString = (LPWSTR)GlobalLock(hClip);
-
                        if (uniString != NULL)
                        {
-                           vboxrc = VbglR3ClipboardWriteData(pCtx->u32ClientID, VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT,
-                                                             uniString, (lstrlenW(uniString) + 1) * 2);
+                           rc = VbglR3ClipboardWriteData(pCtx->u32ClientID, VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT,
+                                                         uniString, (lstrlenW(uniString) + 1) * 2);
                            GlobalUnlock(hClip);
                        }
@@ -483,6 +485,6 @@
                            if (lp != NULL)
                            {
-                               vboxrc = VbglR3ClipboardWriteData(pCtx->u32ClientID, VBOX_SHARED_CLIPBOARD_FMT_HTML,
-                                                                 lp, GlobalSize(hClip));
+                               rc = VbglR3ClipboardWriteData(pCtx->u32ClientID, VBOX_SHARED_CLIPBOARD_FMT_HTML,
+                                                             lp, GlobalSize(hClip));
                                GlobalUnlock(hClip);
                            }
@@ -497,21 +499,19 @@
                else if (u32Formats & VBOX_SHARED_CLIPBOARD_FMT_URI_LIST)
                {
-                   UINT format = RegisterClipboardFormat(VBOX_CLIPBOARD_WIN_REGFMT_URI_LIST);
-                   if (format != 0)
+                   /* 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. */
+                   hClip = GetClipboardData(CF_HDROP);
+                   if (hClip)
                    {
-                       hClip = GetClipboardData(format);
-                       if (hClip)
+                       HDROP hDrop = (HDROP)GlobalLock(hClip);
+                       if (hDrop)
                        {
-                           HDROP hDrop = (HDROP)GlobalLock(hClip);
-                           if (hDrop)
-                           {
-            /*                    vboxrc = VbglR3ClipboardWriteData(pCtx->u32ClientID, VBOX_SHARED_CLIPBOARD_FMT_URI_LIST,
-                                                                 );*/
-                               GlobalUnlock(hClip);
-                           }
-                           else
-                           {
-                               hClip = NULL;
-                           }
+        /*                    vboxrc = VbglR3ClipboardWriteData(pCtx->u32ClientID, VBOX_SHARED_CLIPBOARD_FMT_URI_LIST,
+                                                             );*/
+                           GlobalUnlock(hClip);
+                       }
+                       else
+                       {
+                           hClip = NULL;
                        }
                    }
@@ -543,5 +543,5 @@
         default:
         {
-            rc = DefWindowProc(hwnd, msg, wParam, lParam);
+            lresultRc = DefWindowProc(hwnd, msg, wParam, lParam);
         }
         break;
@@ -549,7 +549,7 @@
 
 #ifndef DEBUG_andy
-    LogFlowFunc(("vboxClipboardProcessMsg returned with rc = %ld\n", rc));
+    LogFlowFunc(("vboxClipboardProcessMsg returned with lresultRc=%ld\n", lresultRc));
 #endif
-    return rc;
+    return lresultRc;
 }
 
Index: /trunk/src/VBox/GuestHost/SharedClipboard/ClipboardCache.cpp
===================================================================
--- /trunk/src/VBox/GuestHost/SharedClipboard/ClipboardCache.cpp	(revision 78501)
+++ /trunk/src/VBox/GuestHost/SharedClipboard/ClipboardCache.cpp	(revision 78501)
@@ -0,0 +1,332 @@
+/* $Id$ */
+/** @file
+ * Shared Clipboard - Cache handling.
+ */
+
+/*
+ * Copyright (C) 2019 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+
+/*********************************************************************************************************************************
+*   Header Files                                                                                                                 *
+*********************************************************************************************************************************/
+#define LOG_GROUP LOG_GROUP_SHARED_CLIPBOARD
+#include <VBox/GuestHost/SharedClipboard-uri.h>
+
+#include <iprt/asm.h>
+#include <iprt/assert.h>
+#include <iprt/dir.h>
+#include <iprt/err.h>
+#include <iprt/file.h>
+#include <iprt/path.h>
+#include <iprt/string.h>
+
+
+#include <VBox/log.h>
+
+SharedClipboardCache::SharedClipboardCache(void)
+    : m_cRefs(0)
+    , m_fOpen(0)
+    , m_hDir(NULL)
+{
+    int rc = initInternal();
+    if (RT_FAILURE(rc))
+        throw rc;
+}
+
+SharedClipboardCache::SharedClipboardCache(const char *pszPath,
+                                           SHAREDCLIPBOARDCACHEFLAGS fFlags /* = SHAREDCLIPBOARDCACHE_FLAGS_NONE */)
+    : m_cRefs(0)
+    , m_fOpen(0)
+    , m_hDir(NULL)
+{
+    int rc = initInternal();
+    if (RT_SUCCESS(rc))
+        rc = OpenEx(pszPath, fFlags);
+
+    if (RT_FAILURE(rc))
+        throw rc;
+}
+
+SharedClipboardCache::~SharedClipboardCache(void)
+{
+    /* Only make sure to not leak any handles and stuff, don't delete any
+     * directories / files here. */
+    closeInternal();
+
+    int rc = destroyInternal();
+    AssertRC(rc);
+}
+
+/**
+ * Adds a reference to a Shared Clipboard cache.
+ *
+ * @returns New reference count.
+ */
+uint16_t SharedClipboardCache::AddRef(void)
+{
+    return ASMAtomicIncU16(&m_cRefs);
+}
+
+/**
+ * Removes a reference from a Shared Clipboard cache.
+ *
+ * @returns New reference count.
+ */
+uint16_t SharedClipboardCache::Release(void)
+{
+    Assert(m_cRefs);
+    return ASMAtomicDecU16(&m_cRefs);
+}
+
+/**
+ * Locks a Shared Clipboard cache.
+ *
+ * @returns VBox status code.
+ */
+int SharedClipboardCache::Lock(void)
+{
+    return RTCritSectEnter(&m_CritSect);
+}
+
+/**
+ * Unlocks a Shared Clipboard cache.
+ *
+ * @returns VBox status code.
+ */
+int SharedClipboardCache::Unlock(void)
+{
+    return RTCritSectLeave(&m_CritSect);
+}
+
+int SharedClipboardCache::AddFile(const char *pszFile)
+{
+    AssertPtrReturn(pszFile, VERR_INVALID_POINTER);
+
+    if (!this->m_lstFiles.contains(pszFile))
+        this->m_lstFiles.append(pszFile);
+    return VINF_SUCCESS;
+}
+
+int SharedClipboardCache::AddDir(const char *pszDir)
+{
+    AssertPtrReturn(pszDir, VERR_INVALID_POINTER);
+
+    if (!this->m_lstDirs.contains(pszDir))
+        this->m_lstDirs.append(pszDir);
+    return VINF_SUCCESS;
+}
+
+int SharedClipboardCache::initInternal(void)
+{
+    return RTCritSectInit(&m_CritSect);
+}
+
+int SharedClipboardCache::destroyInternal(void)
+{
+    return RTCritSectDelete(&m_CritSect);
+}
+
+int SharedClipboardCache::closeInternal(void)
+{
+    int rc;
+    if (this->m_hDir != NULL)
+    {
+        rc = RTDirClose(this->m_hDir);
+        if (RT_SUCCESS(rc))
+            this->m_hDir = NULL;
+    }
+    else
+        rc = VINF_SUCCESS;
+
+    LogFlowFuncLeaveRC(rc);
+    return rc;
+}
+
+int SharedClipboardCache::Close(void)
+{
+    return closeInternal();
+}
+
+const char *SharedClipboardCache::GetDirAbs(void) const
+{
+    return this->m_strPathAbs.c_str();
+}
+
+bool SharedClipboardCache::IsOpen(void) const
+{
+    return (this->m_hDir != NULL);
+}
+
+int SharedClipboardCache::OpenEx(const char *pszPath, SHAREDCLIPBOARDCACHEFLAGS fFlags /* = SHAREDCLIPBOARDCACHE_FLAGS_NONE */)
+{
+    AssertPtrReturn(pszPath, VERR_INVALID_POINTER);
+    AssertReturn(fFlags == 0, VERR_INVALID_PARAMETER); /* Flags not supported yet. */
+
+    int rc;
+
+    do
+    {
+        char pszDropDir[RTPATH_MAX];
+        RTStrPrintf(pszDropDir, sizeof(pszDropDir), "%s", pszPath);
+
+        /** @todo On Windows we also could use the registry to override
+         *        this path, on Posix a dotfile and/or a guest property
+         *        can be used. */
+
+        /* Append our base drop directory. */
+        rc = RTPathAppend(pszDropDir, sizeof(pszDropDir), "VirtualBox Shared Clipboard Files"); /** @todo Make this tag configurable? */
+        if (RT_FAILURE(rc))
+            break;
+
+        /* Create it when necessary. */
+        if (!RTDirExists(pszDropDir))
+        {
+            rc = RTDirCreateFullPath(pszDropDir, RTFS_UNIX_IRWXU);
+            if (RT_FAILURE(rc))
+                break;
+        }
+
+        /* The actually drop directory consist of the current time stamp and a
+         * unique number when necessary. */
+        char pszTime[64];
+        RTTIMESPEC time;
+        if (!RTTimeSpecToString(RTTimeNow(&time), pszTime, sizeof(pszTime)))
+        {
+            rc = VERR_BUFFER_OVERFLOW;
+            break;
+        }
+
+        rc = SharedClipboardPathSanitizeFilename(pszTime, sizeof(pszTime));
+        if (RT_FAILURE(rc))
+            break;
+
+        rc = RTPathAppend(pszDropDir, sizeof(pszDropDir), pszTime);
+        if (RT_FAILURE(rc))
+            break;
+
+        /* Create it (only accessible by the current user) */
+        rc = RTDirCreateUniqueNumbered(pszDropDir, sizeof(pszDropDir), RTFS_UNIX_IRWXU, 3, '-');
+        if (RT_SUCCESS(rc))
+        {
+            RTDIR hDir;
+            rc = RTDirOpen(&hDir, pszDropDir);
+            if (RT_SUCCESS(rc))
+            {
+                this->m_hDir       = hDir;
+                this->m_strPathAbs = pszDropDir;
+                this->m_fOpen      = fFlags;
+            }
+        }
+
+    } while (0);
+
+    LogFlowFuncLeaveRC(rc);
+    return rc;
+}
+
+int SharedClipboardCache::OpenTemp(SHAREDCLIPBOARDCACHEFLAGS fFlags /* = SHAREDCLIPBOARDCACHE_FLAGS_NONE */)
+{
+    AssertReturn(fFlags == 0, VERR_INVALID_PARAMETER); /* Flags not supported yet. */
+
+    /*
+     * Get the user's temp directory. Don't use the user's root directory (or
+     * something inside it) because we don't know for how long/if the data will
+     * be kept after the guest OS used it.
+     */
+    char szTemp[RTPATH_MAX];
+    int rc = RTPathTemp(szTemp, sizeof(szTemp));
+    if (RT_SUCCESS(rc))
+        rc = OpenEx(szTemp, fFlags);
+
+    return rc;
+}
+
+int SharedClipboardCache::Reset(bool fRemoveDropDir)
+{
+    int rc = closeInternal();
+    if (RT_SUCCESS(rc))
+    {
+        if (fRemoveDropDir)
+        {
+            rc = Rollback();
+        }
+        else
+        {
+            this->m_lstDirs.clear();
+            this->m_lstFiles.clear();
+        }
+    }
+
+    LogFlowFuncLeaveRC(rc);
+    return rc;
+}
+
+int SharedClipboardCache::Reopen(void)
+{
+    if (this->m_strPathAbs.isEmpty())
+        return VERR_NOT_FOUND;
+
+    return OpenEx(this->m_strPathAbs.c_str(), this->m_fOpen);
+}
+
+int SharedClipboardCache::Rollback(void)
+{
+    if (this->m_strPathAbs.isEmpty())
+        return VINF_SUCCESS;
+
+    int rc = VINF_SUCCESS;
+
+    /* Rollback by removing any stuff created.
+     * Note: Only remove empty directories, never ever delete
+     *       anything recursive here! Steam (tm) knows best ... :-) */
+    int rc2;
+    for (size_t i = 0; i < this->m_lstFiles.size(); i++)
+    {
+        rc2 = RTFileDelete(this->m_lstFiles.at(i).c_str());
+        if (RT_SUCCESS(rc2))
+            this->m_lstFiles.removeAt(i);
+        else if (RT_SUCCESS(rc))
+           rc = rc2;
+        /* Keep going. */
+    }
+
+    for (size_t i = 0; i < this->m_lstDirs.size(); i++)
+    {
+        rc2 = RTDirRemove(this->m_lstDirs.at(i).c_str());
+        if (RT_SUCCESS(rc2))
+            this->m_lstDirs.removeAt(i);
+        else if (RT_SUCCESS(rc))
+            rc = rc2;
+        /* Keep going. */
+    }
+
+    if (RT_SUCCESS(rc))
+    {
+        Assert(this->m_lstFiles.isEmpty());
+        Assert(this->m_lstDirs.isEmpty());
+
+        rc2 = closeInternal();
+        if (RT_SUCCESS(rc2))
+        {
+            /* Try to remove the empty root dropped files directory as well.
+             * Might return VERR_DIR_NOT_EMPTY or similar. */
+            rc2 = RTDirRemove(this->m_strPathAbs.c_str());
+        }
+        if (RT_SUCCESS(rc))
+            rc = rc2;
+    }
+
+    LogFlowFuncLeaveRC(rc);
+    return rc;
+}
+
Index: unk/src/VBox/GuestHost/SharedClipboard/ClipboardFiles.cpp
===================================================================
--- /trunk/src/VBox/GuestHost/SharedClipboard/ClipboardFiles.cpp	(revision 78500)
+++ 	(revision )
@@ -1,265 +1,0 @@
-/* $Id$ */
-/** @file
- * Shared Clipboard - Directory handling.
- */
-
-/*
- * Copyright (C) 2019 Oracle Corporation
- *
- * This file is part of VirtualBox Open Source Edition (OSE), as
- * available from http://www.virtualbox.org. This file is free software;
- * you can redistribute it and/or modify it under the terms of the GNU
- * General Public License (GPL) as published by the Free Software
- * Foundation, in version 2 as it comes in the "COPYING" file of the
- * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
- * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
- */
-
-
-/*********************************************************************************************************************************
-*   Header Files                                                                                                                 *
-*********************************************************************************************************************************/
-#define LOG_GROUP LOG_GROUP_SHARED_CLIPBOARD
-#include <VBox/GuestHost/SharedClipboard-uri.h>
-
-#include <iprt/assert.h>
-#include <iprt/dir.h>
-#include <iprt/err.h>
-#include <iprt/file.h>
-#include <iprt/path.h>
-#include <iprt/string.h>
-
-
-#include <VBox/log.h>
-
-SharedClipboardDroppedFiles::SharedClipboardDroppedFiles(void)
-    : m_fOpen(0)
-    , m_hDir(NULL) { }
-
-SharedClipboardDroppedFiles::SharedClipboardDroppedFiles(const char *pszPath,
-                                                         SHAREDCLIPBOARDURIDROPPEDFILEFLAGS fFlags /* = SHAREDCLIPBOARDURIDROPPEDFILE_FLAGS_NONE */)
-    : m_fOpen(0)
-    , m_hDir(NULL)
-{
-    OpenEx(pszPath, fFlags);
-}
-
-SharedClipboardDroppedFiles::~SharedClipboardDroppedFiles(void)
-{
-    /* Only make sure to not leak any handles and stuff, don't delete any
-     * directories / files here. */
-    closeInternal();
-}
-
-int SharedClipboardDroppedFiles::AddFile(const char *pszFile)
-{
-    AssertPtrReturn(pszFile, VERR_INVALID_POINTER);
-
-    if (!this->m_lstFiles.contains(pszFile))
-        this->m_lstFiles.append(pszFile);
-    return VINF_SUCCESS;
-}
-
-int SharedClipboardDroppedFiles::AddDir(const char *pszDir)
-{
-    AssertPtrReturn(pszDir, VERR_INVALID_POINTER);
-
-    if (!this->m_lstDirs.contains(pszDir))
-        this->m_lstDirs.append(pszDir);
-    return VINF_SUCCESS;
-}
-
-int SharedClipboardDroppedFiles::closeInternal(void)
-{
-    int rc;
-    if (this->m_hDir != NULL)
-    {
-        rc = RTDirClose(this->m_hDir);
-        if (RT_SUCCESS(rc))
-            this->m_hDir = NULL;
-    }
-    else
-        rc = VINF_SUCCESS;
-
-    LogFlowFuncLeaveRC(rc);
-    return rc;
-}
-
-int SharedClipboardDroppedFiles::Close(void)
-{
-    return closeInternal();
-}
-
-const char *SharedClipboardDroppedFiles::GetDirAbs(void) const
-{
-    return this->m_strPathAbs.c_str();
-}
-
-bool SharedClipboardDroppedFiles::IsOpen(void) const
-{
-    return (this->m_hDir != NULL);
-}
-
-int SharedClipboardDroppedFiles::OpenEx(const char *pszPath, SHAREDCLIPBOARDURIDROPPEDFILEFLAGS fFlags /* = SHAREDCLIPBOARDURIDROPPEDFILE_FLAGS_NONE */)
-{
-    AssertPtrReturn(pszPath, VERR_INVALID_POINTER);
-    AssertReturn(fFlags == 0, VERR_INVALID_PARAMETER); /* Flags not supported yet. */
-
-    int rc;
-
-    do
-    {
-        char pszDropDir[RTPATH_MAX];
-        RTStrPrintf(pszDropDir, sizeof(pszDropDir), "%s", pszPath);
-
-        /** @todo On Windows we also could use the registry to override
-         *        this path, on Posix a dotfile and/or a guest property
-         *        can be used. */
-
-        /* Append our base drop directory. */
-        rc = RTPathAppend(pszDropDir, sizeof(pszDropDir), "VirtualBox Shared Clipboard Files"); /** @todo Make this tag configurable? */
-        if (RT_FAILURE(rc))
-            break;
-
-        /* Create it when necessary. */
-        if (!RTDirExists(pszDropDir))
-        {
-            rc = RTDirCreateFullPath(pszDropDir, RTFS_UNIX_IRWXU);
-            if (RT_FAILURE(rc))
-                break;
-        }
-
-        /* The actually drop directory consist of the current time stamp and a
-         * unique number when necessary. */
-        char pszTime[64];
-        RTTIMESPEC time;
-        if (!RTTimeSpecToString(RTTimeNow(&time), pszTime, sizeof(pszTime)))
-        {
-            rc = VERR_BUFFER_OVERFLOW;
-            break;
-        }
-
-        rc = SharedClipboardPathSanitizeFilename(pszTime, sizeof(pszTime));
-        if (RT_FAILURE(rc))
-            break;
-
-        rc = RTPathAppend(pszDropDir, sizeof(pszDropDir), pszTime);
-        if (RT_FAILURE(rc))
-            break;
-
-        /* Create it (only accessible by the current user) */
-        rc = RTDirCreateUniqueNumbered(pszDropDir, sizeof(pszDropDir), RTFS_UNIX_IRWXU, 3, '-');
-        if (RT_SUCCESS(rc))
-        {
-            RTDIR hDir;
-            rc = RTDirOpen(&hDir, pszDropDir);
-            if (RT_SUCCESS(rc))
-            {
-                this->m_hDir       = hDir;
-                this->m_strPathAbs = pszDropDir;
-                this->m_fOpen      = fFlags;
-            }
-        }
-
-    } while (0);
-
-    LogFlowFuncLeaveRC(rc);
-    return rc;
-}
-
-int SharedClipboardDroppedFiles::OpenTemp(SHAREDCLIBOARDURIDROPPEDFILEFLAGS fFlags /* = SHAREDCLIPBOARDURIDROPPEDFILE_FLAGS_NONE */)
-{
-    AssertReturn(fFlags == 0, VERR_INVALID_PARAMETER); /* Flags not supported yet. */
-
-    /*
-     * Get the user's temp directory. Don't use the user's root directory (or
-     * something inside it) because we don't know for how long/if the data will
-     * be kept after the guest OS used it.
-     */
-    char szTemp[RTPATH_MAX];
-    int rc = RTPathTemp(szTemp, sizeof(szTemp));
-    if (RT_SUCCESS(rc))
-        rc = OpenEx(szTemp, fFlags);
-
-    return rc;
-}
-
-int SharedClipboardDroppedFiles::Reset(bool fRemoveDropDir)
-{
-    int rc = closeInternal();
-    if (RT_SUCCESS(rc))
-    {
-        if (fRemoveDropDir)
-        {
-            rc = Rollback();
-        }
-        else
-        {
-            this->m_lstDirs.clear();
-            this->m_lstFiles.clear();
-        }
-    }
-
-    LogFlowFuncLeaveRC(rc);
-    return rc;
-}
-
-int SharedClipboardDroppedFiles::Reopen(void)
-{
-    if (this->m_strPathAbs.isEmpty())
-        return VERR_NOT_FOUND;
-
-    return OpenEx(this->m_strPathAbs.c_str(), this->m_fOpen);
-}
-
-int SharedClipboardDroppedFiles::Rollback(void)
-{
-    if (this->m_strPathAbs.isEmpty())
-        return VINF_SUCCESS;
-
-    int rc = VINF_SUCCESS;
-
-    /* Rollback by removing any stuff created.
-     * Note: Only remove empty directories, never ever delete
-     *       anything recursive here! Steam (tm) knows best ... :-) */
-    int rc2;
-    for (size_t i = 0; i < this->m_lstFiles.size(); i++)
-    {
-        rc2 = RTFileDelete(this->m_lstFiles.at(i).c_str());
-        if (RT_SUCCESS(rc2))
-            this->m_lstFiles.removeAt(i);
-        else if (RT_SUCCESS(rc))
-           rc = rc2;
-        /* Keep going. */
-    }
-
-    for (size_t i = 0; i < this->m_lstDirs.size(); i++)
-    {
-        rc2 = RTDirRemove(this->m_lstDirs.at(i).c_str());
-        if (RT_SUCCESS(rc2))
-            this->m_lstDirs.removeAt(i);
-        else if (RT_SUCCESS(rc))
-            rc = rc2;
-        /* Keep going. */
-    }
-
-    if (RT_SUCCESS(rc))
-    {
-        Assert(this->m_lstFiles.isEmpty());
-        Assert(this->m_lstDirs.isEmpty());
-
-        rc2 = closeInternal();
-        if (RT_SUCCESS(rc2))
-        {
-            /* Try to remove the empty root dropped files directory as well.
-             * Might return VERR_DIR_NOT_EMPTY or similar. */
-            rc2 = RTDirRemove(this->m_strPathAbs.c_str());
-        }
-        if (RT_SUCCESS(rc))
-            rc = rc2;
-    }
-
-    LogFlowFuncLeaveRC(rc);
-    return rc;
-}
-
Index: /trunk/src/VBox/GuestHost/SharedClipboard/ClipboardPath.cpp
===================================================================
--- /trunk/src/VBox/GuestHost/SharedClipboard/ClipboardPath.cpp	(revision 78500)
+++ /trunk/src/VBox/GuestHost/SharedClipboard/ClipboardPath.cpp	(revision 78501)
@@ -64,8 +64,16 @@
 }
 
+/**
+ * Sanitizes a given path regarding invalid / unhandled characters.
+ * Currently not implemented.
+ *
+ * @returns VBox status code.
+ * @param   pszPath             Path to sanitize. UTF-8.
+ * @param   cbPath              Size (in bytes) of the path to sanitize.
+ */
 int SharedClipboardPathSanitize(char *pszPath, size_t cbPath)
 {
     /** @todo */
-    RT_NOREF2(pszPath, cbPath);
+    RT_NOREF(pszPath, cbPath);
     return VINF_SUCCESS;
 }
Index: /trunk/src/VBox/GuestHost/SharedClipboard/clipboard-win.cpp
===================================================================
--- /trunk/src/VBox/GuestHost/SharedClipboard/clipboard-win.cpp	(revision 78500)
+++ /trunk/src/VBox/GuestHost/SharedClipboard/clipboard-win.cpp	(revision 78501)
@@ -22,8 +22,15 @@
 #include <iprt/thread.h>
 
+#ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
+# include <iprt/utf16.h>
+#endif
+
 #define LOG_GROUP LOG_GROUP_SHARED_CLIPBOARD
 #include <VBox/log.h>
 
 #include <VBox/GuestHost/SharedClipboard.h>
+#ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
+# include <VBox/GuestHost/SharedClipboard-uri.h>
+#endif
 #include <VBox/GuestHost/SharedClipboard-win.h>
 #include <VBox/GuestHost/clipboard-helper.h>
@@ -277,4 +284,10 @@
 }
 
+/**
+ * Converts a (registered or standard) Windows clipboard format to a VBox clipboard format.
+ *
+ * @returns Converted VBox clipboard format, or VBOX_SHARED_CLIPBOARD_FMT_NONE if not found.
+ * @param   uFormat             Windows clipboard format to convert.
+ */
 VBOXCLIPBOARDFORMAT VBoxClipboardWinClipboardFormatToVBox(UINT uFormat)
 {
@@ -284,32 +297,37 @@
     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;
+        case CF_UNICODETEXT:
+            vboxFormat = VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT;
+            break;
+
+        case CF_DIB:
+            vboxFormat = VBOX_SHARED_CLIPBOARD_FMT_BITMAP;
+            break;
+
 #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;
+        /* Handles file system entries which are locally present
+         * on source for transferring to the target. */
+        case CF_HDROP:
+            vboxFormat = VBOX_SHARED_CLIPBOARD_FMT_URI_LIST;
+            break;
 #endif
-              }
-          }
-          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)
+                {
+                    LogFlowFunc(("uFormat=%u -> szFormatName=%s\n", uFormat, szFormatName));
+
+                    if (RTStrCmp(szFormatName, VBOX_CLIPBOARD_WIN_REGFMT_HTML) == 0)
+                        vboxFormat = VBOX_SHARED_CLIPBOARD_FMT_HTML;
+                }
+            }
+            break;
+    }
+
+    LogFlowFunc(("uFormat=%u -> vboxFormat=0x%x\n", uFormat, vboxFormat));
     return vboxFormat;
 }
@@ -354,2 +372,373 @@
 }
 
+/**
+ * Extracts a field value from CF_HTML data.
+ *
+ * @returns VBox status code.
+ * @param   pszSrc      source in CF_HTML format.
+ * @param   pszOption   Name of CF_HTML field.
+ * @param   puValue     Where to return extracted value of CF_HTML field.
+ */
+int VBoxClipboardWinGetCFHTMLHeaderValue(const char *pszSrc, const char *pszOption, uint32_t *puValue)
+{
+    AssertPtrReturn(pszSrc, VERR_INVALID_POINTER);
+    AssertPtrReturn(pszOption, VERR_INVALID_POINTER);
+
+    int rc = VERR_INVALID_PARAMETER;
+
+    const char *pszOptionValue = RTStrStr(pszSrc, pszOption);
+    if (pszOptionValue)
+    {
+        size_t cchOption = strlen(pszOption);
+        Assert(cchOption);
+
+        rc = RTStrToUInt32Ex(pszOptionValue + cchOption, NULL, 10, puValue);
+    }
+    return rc;
+}
+
+/**
+ * Check that the source string contains CF_HTML struct.
+ *
+ * @returns @c true if the @a pszSource string is in CF_HTML format.
+ * @param   pszSource   Source string to check.
+ */
+bool VBoxClipboardWinIsCFHTML(const char *pszSource)
+{
+    return    RTStrStr(pszSource, "Version:") != NULL
+           && RTStrStr(pszSource, "StartHTML:") != NULL;
+}
+
+/**
+ * Converts clipboard data from CF_HTML format to MIME clipboard format.
+ *
+ * Returns allocated buffer that contains html converted to text/html mime type
+ *
+ * @returns VBox status code.
+ * @param   pszSource   The input.
+ * @param   cch         The length of the input.
+ * @param   ppszOutput  Where to return the result.  Free using RTMemFree.
+ * @param   pcbOutput   Where to the return length of the result (bytes/chars).
+ */
+int VBoxClipboardWinConvertCFHTMLToMIME(const char *pszSource, const uint32_t cch, char **ppszOutput, uint32_t *pcbOutput)
+{
+    Assert(pszSource);
+    Assert(cch);
+    Assert(ppszOutput);
+    Assert(pcbOutput);
+
+    uint32_t offStart;
+    int rc = VBoxClipboardWinGetCFHTMLHeaderValue(pszSource, "StartFragment:", &offStart);
+    if (RT_SUCCESS(rc))
+    {
+        uint32_t offEnd;
+        rc = VBoxClipboardWinGetCFHTMLHeaderValue(pszSource, "EndFragment:", &offEnd);
+        if (RT_SUCCESS(rc))
+        {
+            if (   offStart > 0
+                && offEnd > 0
+                && offEnd > offStart
+                && offEnd <= cch)
+            {
+                uint32_t cchSubStr = offEnd - offStart;
+                char *pszResult = (char *)RTMemAlloc(cchSubStr + 1);
+                if (pszResult)
+                {
+                    rc = RTStrCopyEx(pszResult, cchSubStr + 1, pszSource + offStart, cchSubStr);
+                    if (RT_SUCCESS(rc))
+                    {
+                        *ppszOutput = pszResult;
+                        *pcbOutput  = (uint32_t)(cchSubStr + 1);
+                        rc = VINF_SUCCESS;
+                    }
+                    else
+                    {
+                        LogRelFlowFunc(("Error: Unknown CF_HTML format. Expected EndFragment. rc = %Rrc\n", rc));
+                        RTMemFree(pszResult);
+                    }
+                }
+                else
+                {
+                    LogRelFlowFunc(("Error: Unknown CF_HTML format. Expected EndFragment\n"));
+                    rc = VERR_NO_MEMORY;
+                }
+            }
+            else
+            {
+                LogRelFlowFunc(("Error: CF_HTML out of bounds - offStart=%#x offEnd=%#x cch=%#x\n", offStart, offEnd, cch));
+                rc = VERR_INVALID_PARAMETER;
+            }
+        }
+        else
+        {
+            LogRelFlowFunc(("Error: Unknown CF_HTML format. Expected EndFragment. rc = %Rrc\n", rc));
+            rc = VERR_INVALID_PARAMETER;
+        }
+    }
+    else
+    {
+        LogRelFlowFunc(("Error: Unknown CF_HTML format. Expected StartFragment. rc = %Rrc\n", rc));
+        rc = VERR_INVALID_PARAMETER;
+    }
+
+    return rc;
+}
+
+/**
+ * Converts source UTF-8 MIME HTML clipboard data to UTF-8 CF_HTML format.
+ *
+ * This is just encapsulation work, slapping a header on the data.
+ *
+ * It allocates [..]
+ *
+ * Calculations:
+ *   Header length = format Length + (2*(10 - 5('%010d'))('digits')) - 2('%s') = format length + 8
+ *   EndHtml       = Header length + fragment length
+ *   StartHtml     = 105(constant)
+ *   StartFragment = 141(constant) may vary if the header html content will be extended
+ *   EndFragment   = Header length + fragment length - 38(ending length)
+ *
+ * @param   pszSource   Source buffer that contains utf-16 string in mime html format
+ * @param   cb          Size of source buffer in bytes
+ * @param   ppszOutput  Where to return the allocated output buffer to put converted UTF-8
+ *                      CF_HTML clipboard data.  This function allocates memory for this.
+ * @param   pcbOutput   Where to return the size of allocated result buffer in bytes/chars, including zero terminator
+ *
+ * @note    output buffer should be free using RTMemFree()
+ * @note    Everything inside of fragment can be UTF8. Windows allows it. Everything in header should be Latin1.
+ */
+int VBoxClipboardWinConvertMIMEToCFHTML(const char *pszSource, size_t cb, char **ppszOutput, uint32_t *pcbOutput)
+{
+    Assert(ppszOutput);
+    Assert(pcbOutput);
+    Assert(pszSource);
+    Assert(cb);
+
+    /* construct CF_HTML formatted string */
+    char *pszResult = NULL;
+    size_t cchFragment;
+    int rc = RTStrNLenEx(pszSource, cb, &cchFragment);
+    if (!RT_SUCCESS(rc))
+    {
+        LogRelFlowFunc(("Error: invalid source fragment. rc = %Rrc\n"));
+        return VERR_INVALID_PARAMETER;
+    }
+
+    /*
+    @StartHtml - pos before <html>
+    @EndHtml - whole size of text excluding ending zero char
+    @StartFragment - pos after <!--StartFragment-->
+    @EndFragment - pos before <!--EndFragment-->
+    @note: all values includes CR\LF inserted into text
+    Calculations:
+    Header length = format Length + (3*6('digits')) - 2('%s') = format length + 16 (control value - 183)
+    EndHtml  = Header length + fragment length
+    StartHtml = 105(constant)
+    StartFragment = 143(constant)
+    EndFragment  = Header length + fragment length - 40(ending length)
+    */
+    static const char s_szFormatSample[] =
+    /*   0:   */ "Version:1.0\r\n"
+    /*  13:   */ "StartHTML:000000101\r\n"
+    /*  34:   */ "EndHTML:%0000009u\r\n" // END HTML = Header length + fragment length
+    /*  53:   */ "StartFragment:000000137\r\n"
+    /*  78:   */ "EndFragment:%0000009u\r\n"
+    /* 101:   */ "<html>\r\n"
+    /* 109:   */ "<body>\r\n"
+    /* 117:   */ "<!--StartFragment-->"
+    /* 137:   */ "%s"
+    /* 137+2: */ "<!--EndFragment-->\r\n"
+    /* 157+2: */ "</body>\r\n"
+    /* 166+2: */ "</html>\r\n";
+    /* 175+2: */
+    AssertCompile(sizeof(s_szFormatSample) == 175 + 2 + 1);
+
+    /* calculate parameters of CF_HTML header */
+    size_t cchHeader      = sizeof(s_szFormatSample) - 1;
+    size_t offEndHtml     = cchHeader + cchFragment;
+    size_t offEndFragment = cchHeader + cchFragment - 38; /* 175-137 = 38 */
+    pszResult = (char *)RTMemAlloc(offEndHtml + 1);
+    if (pszResult == NULL)
+    {
+        LogRelFlowFunc(("Error: Cannot allocate memory for result buffer. rc = %Rrc\n"));
+        return VERR_NO_MEMORY;
+    }
+
+    /* format result CF_HTML string */
+    size_t cchFormatted = RTStrPrintf(pszResult, offEndHtml + 1,
+                                      s_szFormatSample, offEndHtml, offEndFragment, pszSource);
+    Assert(offEndHtml == cchFormatted); NOREF(cchFormatted);
+
+#ifdef VBOX_STRICT
+    /* Control calculations. check consistency.*/
+    static const char s_szStartFragment[] = "<!--StartFragment-->";
+    static const char s_szEndFragment[] = "<!--EndFragment-->";
+
+    /* check 'StartFragment:' value */
+    const char *pszRealStartFragment = RTStrStr(pszResult, s_szStartFragment);
+    Assert(&pszRealStartFragment[sizeof(s_szStartFragment) - 1] - pszResult == 137);
+
+    /* check 'EndFragment:' value */
+    const char *pszRealEndFragment = RTStrStr(pszResult, s_szEndFragment);
+    Assert((size_t)(pszRealEndFragment - pszResult) == offEndFragment);
+#endif
+
+    *ppszOutput = pszResult;
+    *pcbOutput = (uint32_t)cchFormatted + 1;
+    Assert(*pcbOutput == cchFormatted + 1);
+
+    return VINF_SUCCESS;
+}
+
+#ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
+/**
+ * Converts a DROPFILES (HDROP) structure to a string list, separated by \r\n.
+ *
+ * @returns VBox status code.
+ * @param   pDropFiles          Pointer to DROPFILES structure to convert.
+ * @param   ppvData             Where to return the converted (allocated) data on success.
+ * @param   pcbData             Size (in bytes) of the allocated data returned.
+ */
+int VBoxClipboardWinDropFilesToStringList(DROPFILES *pDropFiles, void **ppvData, size_t *pcbData)
+{
+    AssertPtrReturn(pDropFiles, VERR_INVALID_POINTER);
+    AssertPtrReturn(ppvData,    VERR_INVALID_POINTER);
+    AssertPtrReturn(pcbData,    VERR_INVALID_POINTER);
+
+    /* Do we need to do Unicode stuff? */
+    const bool fUnicode = RT_BOOL(pDropFiles->fWide);
+
+    /* Get the offset of the file list. */
+    Assert(pDropFiles->pFiles >= sizeof(DROPFILES));
+
+    /* Note: This is *not* pDropFiles->pFiles! DragQueryFile only
+     *       will work with the plain storage medium pointer! */
+    HDROP hDrop = (HDROP)(pDropFiles);
+
+    int rc = VINF_SUCCESS;
+
+    /* First, get the file count. */
+    /** @todo Does this work on Windows 2000 / NT4? */
+    char *pszFiles = NULL;
+    uint32_t cchFiles = 0;
+    UINT cFiles = DragQueryFile(hDrop, UINT32_MAX /* iFile */, NULL /* lpszFile */, 0 /* cchFile */);
+
+    LogFlowFunc(("Got %RU16 file(s), fUnicode=%RTbool\n", cFiles, fUnicode));
+
+    for (UINT i = 0; i < cFiles; i++)
+    {
+        UINT cchFile = DragQueryFile(hDrop, i /* File index */, NULL /* Query size first */, 0 /* cchFile */);
+        Assert(cchFile);
+
+        if (RT_FAILURE(rc))
+            break;
+
+        char *pszFileUtf8 = NULL; /* UTF-8 version. */
+        UINT cchFileUtf8 = 0;
+        if (fUnicode)
+        {
+            /* Allocate enough space (including terminator). */
+            WCHAR *pwszFile = (WCHAR *)RTMemAlloc((cchFile + 1) * sizeof(WCHAR));
+            if (pwszFile)
+            {
+                const UINT cwcFileUtf16 = DragQueryFileW(hDrop, i /* File index */,
+                                                         pwszFile, cchFile + 1 /* Include terminator */);
+
+                AssertMsg(cwcFileUtf16 == cchFile, ("cchFileUtf16 (%RU16) does not match cchFile (%RU16)\n",
+                                                    cwcFileUtf16, cchFile));
+                RT_NOREF(cwcFileUtf16);
+
+                rc = RTUtf16ToUtf8(pwszFile, &pszFileUtf8);
+                if (RT_SUCCESS(rc))
+                {
+                    cchFileUtf8 = (UINT)strlen(pszFileUtf8);
+                    Assert(cchFileUtf8);
+                }
+
+                RTMemFree(pwszFile);
+            }
+            else
+                rc = VERR_NO_MEMORY;
+        }
+        else /* ANSI */
+        {
+            /* Allocate enough space (including terminator). */
+            pszFileUtf8 = (char *)RTMemAlloc((cchFile + 1) * sizeof(char));
+            if (pszFileUtf8)
+            {
+                cchFileUtf8 = DragQueryFileA(hDrop, i /* File index */,
+                                             pszFileUtf8, cchFile + 1 /* Include terminator */);
+
+                AssertMsg(cchFileUtf8 == cchFile, ("cchFileUtf8 (%RU16) does not match cchFile (%RU16)\n",
+                                                   cchFileUtf8, cchFile));
+            }
+            else
+                rc = VERR_NO_MEMORY;
+        }
+
+        if (RT_SUCCESS(rc))
+        {
+            LogFlowFunc(("\tFile: %s (cchFile=%RU16)\n", pszFileUtf8, cchFileUtf8));
+
+            LogRel(("DnD: Adding guest file '%s'\n", pszFileUtf8));
+
+            rc = RTStrAAppendExN(&pszFiles, 1 /* cPairs */, pszFileUtf8, cchFileUtf8);
+            if (RT_SUCCESS(rc))
+                cchFiles += cchFileUtf8;
+        }
+        else
+            LogFunc(("Error handling file entry #%u, rc=%Rrc\n", i, rc));
+
+        if (pszFileUtf8)
+            RTStrFree(pszFileUtf8);
+
+        if (RT_FAILURE(rc))
+            break;
+
+        /* Add separation between filenames.
+         * Note: Also do this for the last element of the list. */
+        rc = RTStrAAppendExN(&pszFiles, 1 /* cPairs */, "\r\n", 2 /* Bytes */);
+        if (RT_SUCCESS(rc))
+            cchFiles += 2; /* Include \r\n */
+    }
+
+    if (RT_SUCCESS(rc))
+    {
+        cchFiles += 1; /* Add string termination. */
+        uint32_t cbFiles = cchFiles * sizeof(char);
+
+        LogFlowFunc(("cFiles=%u, cchFiles=%RU32, cbFiles=%RU32, pszFiles=0x%p\n",
+                     cFiles, cchFiles, cbFiles, pszFiles));
+
+        /* Translate the list into URI elements. */
+        SharedClipboardURIList lstURI;
+        rc = lstURI.AppendNativePathsFromList(pszFiles, cbFiles,
+                                              SHAREDCLIPBOARDURILIST_FLAGS_ABSOLUTE_PATHS);
+        if (RT_SUCCESS(rc))
+        {
+            RTCString strRoot = lstURI.GetRootEntries();
+            size_t cbRoot = strRoot.length() + 1; /* Include termination */
+
+            void *pvData = RTMemAlloc(cbRoot);
+            if (pvData)
+            {
+                memcpy(pvData, strRoot.c_str(), cbRoot);
+
+                *ppvData = pvData;
+                *pcbData = cbRoot;
+            }
+            else
+                rc = VERR_NO_MEMORY;
+        }
+    }
+
+    LogFlowFunc(("Building CF_HDROP list rc=%Rrc, pszFiles=0x%p, cFiles=%RU16, cchFiles=%RU32\n",
+                 rc, pszFiles, cFiles, cchFiles));
+
+    if (pszFiles)
+        RTStrFree(pszFiles);
+
+    return rc;
+}
+#endif /* VBOX_WITH_SHARED_CLIPBOARD_URI_LIST */
+
Index: /trunk/src/VBox/HostServices/SharedClipboard/Makefile.kmk
===================================================================
--- /trunk/src/VBox/HostServices/SharedClipboard/Makefile.kmk	(revision 78500)
+++ /trunk/src/VBox/HostServices/SharedClipboard/Makefile.kmk	(revision 78501)
@@ -45,7 +45,9 @@
 ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
  VBoxSharedClipboard_SOURCES += \
+	VBoxSharedClipboardSvc-uri.cpp \
+	$(PATH_ROOT)/src/VBox/GuestHost/SharedClipboard/ClipboardPath.cpp \
+	$(PATH_ROOT)/src/VBox/GuestHost/SharedClipboard/ClipboardCache.cpp \
 	$(PATH_ROOT)/src/VBox/GuestHost/SharedClipboard/ClipboardURIList.cpp \
-	$(PATH_ROOT)/src/VBox/GuestHost/SharedClipboard/ClipboardURIObject.cpp \
-	$(PATH_ROOT)/src/VBox/GuestHost/SharedClipboard/ClipboardPath.cpp
+	$(PATH_ROOT)/src/VBox/GuestHost/SharedClipboard/ClipboardURIObject.cpp
 endif
 if1of ($(KBUILD_TARGET), linux solaris freebsd) ## @todo X11
Index: /trunk/src/VBox/HostServices/SharedClipboard/VBoxClipboard.h
===================================================================
--- /trunk/src/VBox/HostServices/SharedClipboard/VBoxClipboard.h	(revision 78500)
+++ /trunk/src/VBox/HostServices/SharedClipboard/VBoxClipboard.h	(revision 78501)
@@ -1,5 +1,5 @@
 /* $Id$ */
 /** @file
- * Shared Clipboard Service - Internal Header.
+ * Shared Clipboard Service - Internal header.
  */
 
@@ -36,10 +36,14 @@
     uint32_t u32ClientID;
 
-    bool fAsync;        /* Guest is waiting for a message. */
-    bool fReadPending;  /* The guest is waiting for data from the host */
-
-    bool fMsgQuit;
-    bool fMsgReadData;
-    bool fMsgFormats;
+    /** The guest is waiting for a message. */
+    bool fAsync;
+    /** The guest is waiting for data from the host */
+    bool fReadPending;
+    /** Whether the host host has sent a quit message. */
+    bool fHostMsgQuit;
+    /** Whether the host host has requested reading clipboard data from the guest. */
+    bool fHostMsgReadData;
+    /** Whether the host host has reported its available formats. */
+    bool fHostMsgFormats;
 
     struct {
@@ -67,5 +71,5 @@
  * The service functions. Locking is between the service thread and the platform dependent windows thread.
  */
-void vboxSvcClipboardReportMsg (VBOXCLIPBOARDCLIENTDATA *pClient, uint32_t u32Msg, uint32_t u32Formats);
+void vboxSvcClipboardReportMsg(VBOXCLIPBOARDCLIENTDATA *pClient, uint32_t u32Msg, uint32_t u32Formats);
 void vboxSvcClipboardCompleteReadData(VBOXCLIPBOARDCLIENTDATA *pClient, int rc, uint32_t cbActual);
 
@@ -73,12 +77,12 @@
  * Platform dependent functions.
  */
-int vboxClipboardInit (void);
-void vboxClipboardDestroy (void);
+int vboxClipboardInit(void);
+void vboxClipboardDestroy(void);
 
-int vboxClipboardConnect (VBOXCLIPBOARDCLIENTDATA *pClient, bool fHeadless);
-void vboxClipboardDisconnect (VBOXCLIPBOARDCLIENTDATA *pClient);
-void vboxClipboardFormatAnnounce (VBOXCLIPBOARDCLIENTDATA *pClient, uint32_t u32Formats);
-int vboxClipboardReadData (VBOXCLIPBOARDCLIENTDATA *pClient, uint32_t u32Format, void *pv, uint32_t cb, uint32_t *pcbActual);
-void vboxClipboardWriteData (VBOXCLIPBOARDCLIENTDATA *pClient, void *pv, uint32_t cb, uint32_t u32Format);
+int vboxClipboardConnect(VBOXCLIPBOARDCLIENTDATA *pClient, bool fHeadless);
+void vboxClipboardDisconnect(VBOXCLIPBOARDCLIENTDATA *pClient);
+void vboxClipboardFormatAnnounce(VBOXCLIPBOARDCLIENTDATA *pClient, uint32_t u32Formats);
+int vboxClipboardReadData(VBOXCLIPBOARDCLIENTDATA *pClient, uint32_t u32Format, void *pv, uint32_t cb, uint32_t *pcbActual);
+void vboxClipboardWriteData(VBOXCLIPBOARDCLIENTDATA *pClient, void *pv, uint32_t cb, uint32_t u32Format);
 
 int vboxClipboardSync (VBOXCLIPBOARDCLIENTDATA *pClient);
Index: /trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc-uri.cpp
===================================================================
--- /trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc-uri.cpp	(revision 78501)
+++ /trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc-uri.cpp	(revision 78501)
@@ -0,0 +1,49 @@
+/* $Id$ */
+/** @file
+ * Shared Clipboard Service - Internal code for URI (list) handling.
+ */
+
+/*
+ * Copyright (C) 2019 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+
+/*********************************************************************************************************************************
+*   Header Files                                                                                                                 *
+*********************************************************************************************************************************/
+#define LOG_GROUP LOG_GROUP_SHARED_CLIPBOARD
+#include <VBox/HostServices/VBoxClipboardSvc.h>
+
+#include "VBoxSharedClipboardSvc-uri.h"
+
+
+int vboxClipboardSvcURIHandler(uint32_t u32ClientID,
+                               void *pvClient,
+                               uint32_t u32Function,
+                               uint32_t cParms,
+                               VBOXHGCMSVCPARM paParms[],
+                               uint64_t tsArrival,
+                               bool *pfAsync)
+{
+    RT_NOREF(u32ClientID, pvClient, u32Function, cParms, paParms, tsArrival, pfAsync);
+
+    return VINF_SUCCESS;
+}
+
+int vboxClipboardSvcURIHostHandler(uint32_t u32Function,
+                                   uint32_t cParms,
+                                   VBOXHGCMSVCPARM paParms[])
+{
+    RT_NOREF(u32Function, cParms, paParms);
+
+    return VINF_SUCCESS;
+}
+
Index: /trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc-uri.h
===================================================================
--- /trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc-uri.h	(revision 78501)
+++ /trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc-uri.h	(revision 78501)
@@ -0,0 +1,37 @@
+/* $Id$ */
+/** @file
+ * Shared Clipboard Service - Internal header for URI (list) handling.
+ */
+
+/*
+ * Copyright (C) 2019 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+#ifndef VBOX_INCLUDED_SRC_SharedClipboard_VBoxSharedClipboardSvc_uri_h
+#define VBOX_INCLUDED_SRC_SharedClipboard_VBoxSharedClipboardSvc_uri_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+int vboxClipboardSvcURIHandler(uint32_t u32ClientID,
+                               void *pvClient,
+                               uint32_t u32Function,
+                                uint32_t cParms,
+                               VBOXHGCMSVCPARM paParms[],
+                               uint64_t tsArrival,
+                               bool *pfAsync);
+
+int vboxClipboardSvcURIHostHandler(uint32_t u32Function,
+                                   uint32_t cParms,
+                                   VBOXHGCMSVCPARM paParms[]);
+
+#endif /* !VBOX_INCLUDED_SRC_SharedClipboard_VBoxSharedClipboardSvc_uri_h */
+
Index: /trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc-win.cpp
===================================================================
--- /trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc-win.cpp	(revision 78500)
+++ /trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc-win.cpp	(revision 78501)
@@ -52,8 +52,5 @@
 *   Internal Functions                                                                                                           *
 *********************************************************************************************************************************/
-static int ConvertCFHtmlToMime(const char *pszSource, const uint32_t cch, char **ppszOutput, uint32_t *pch);
-static int ConvertMimeToCFHTML(const char *pszSource, size_t cb, char **ppszOutput, uint32_t *pcbOutput);
-static bool IsWindowsHTML(const char *source);
-static int vboxClipboardSyncInternal(PVBOXCLIPBOARDCONTEXT pCtx);
+static int vboxClipboardWinSyncInternal(PVBOXCLIPBOARDCONTEXT pCtx);
 
 struct _VBOXCLIPBOARDCONTEXT
@@ -122,10 +119,10 @@
 
     if (   u32Format == VBOX_SHARED_CLIPBOARD_FMT_HTML
-        && IsWindowsHTML((const char *)pvSrc))
+        && VBoxClipboardWinIsCFHTML((const char *)pvSrc))
     {
         /** @todo r=bird: Why the double conversion? */
         char *pszBuf = NULL;
         uint32_t cbBuf = 0;
-        int rc = ConvertCFHtmlToMime((const char *)pvSrc, cbSrc, &pszBuf, &cbBuf);
+        int rc = VBoxClipboardWinConvertCFHTMLToMIME((const char *)pvSrc, cbSrc, &pszBuf, &cbBuf);
         if (RT_SUCCESS(rc))
         {
@@ -176,5 +173,5 @@
 static LRESULT CALLBACK vboxClipboardWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
 {
-    LRESULT rc = 0;
+    LRESULT lresultRc = 0;
 
     const PVBOXCLIPBOARDCONTEXT pCtx    = &g_ctx;
@@ -190,6 +187,6 @@
             {
                 /* Clipboard was updated by another application, retrieve formats and report back. */
-                int vboxrc = vboxClipboardSyncInternal(pCtx);
-                AssertRC(vboxrc);
+                int rc = vboxClipboardWinSyncInternal(pCtx);
+                AssertRC(rc);
             }
         } break;
@@ -201,5 +198,5 @@
             if (VBoxClipboardWinIsNewAPI(&pWinCtx->newAPI))
             {
-                rc = DefWindowProc(hwnd, msg, wParam, lParam);
+                lresultRc = DefWindowProc(hwnd, msg, wParam, lParam);
                 break;
             }
@@ -221,9 +218,9 @@
                     /* Pass the message further. */
                     DWORD_PTR dwResult;
-                    rc = SendMessageTimeout(pWinCtx->hWndNextInChain, WM_CHANGECBCHAIN, wParam, lParam, 0,
-                                            VBOX_CLIPBOARD_CBCHAIN_TIMEOUT_MS,
-                                            &dwResult);
-                    if (!rc)
-                        rc = (LRESULT)dwResult;
+                    lresultRc = SendMessageTimeout(pWinCtx->hWndNextInChain, WM_CHANGECBCHAIN, wParam, lParam, 0,
+                                                    VBOX_CLIPBOARD_CBCHAIN_TIMEOUT_MS,
+                                                    &dwResult);
+                    if (!lresultRc)
+                        lresultRc = (LRESULT)dwResult;
                 }
             }
@@ -237,5 +234,5 @@
             {
                 /* Clipboard was updated by another application, retrieve formats and report back. */
-                int vboxrc = vboxClipboardSyncInternal(pCtx);
+                int vboxrc = vboxClipboardWinSyncInternal(pCtx);
                 AssertRC(vboxrc);
             }
@@ -244,10 +241,11 @@
             {
                 LogFunc(("WM_DRAWCLIPBOARD next %p\n", pWinCtx->hWndNextInChain));
+
                 /* Pass the message to next windows in the clipboard chain. */
                 DWORD_PTR dwResult;
-                rc = SendMessageTimeout(pWinCtx->hWndNextInChain, msg, wParam, lParam, 0, VBOX_CLIPBOARD_CBCHAIN_TIMEOUT_MS,
-                                        &dwResult);
-                if (!rc)
-                    rc = dwResult;
+                lresultRc = SendMessageTimeout(pWinCtx->hWndNextInChain, msg, wParam, lParam, 0, VBOX_CLIPBOARD_CBCHAIN_TIMEOUT_MS,
+                                               &dwResult);
+                if (!lresultRc)
+                    lresultRc = dwResult;
             }
         } break;
@@ -281,39 +279,12 @@
         case WM_RENDERFORMAT:
         {
+            LogFunc(("WM_RENDERFORMAT\n"));
+
             /* Insert the requested clipboard format data into the clipboard. */
-            VBOXCLIPBOARDFORMAT fFormat = VBOX_SHARED_CLIPBOARD_FMT_NONE;
-
-            UINT format = (UINT)wParam;
-
-            LogFunc(("WM_RENDERFORMAT: Format %u\n", format));
-
-            switch (format)
-            {
-                case CF_UNICODETEXT:
-                    fFormat |= VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT;
-                    break;
-
-                case CF_DIB:
-                    fFormat |= VBOX_SHARED_CLIPBOARD_FMT_BITMAP;
-                    break;
-
-                default:
-                    if (format >= 0xC000)
-                    {
-                        TCHAR szFormatName[256]; /** @todo r=andy Unicode, 256 is enough? */
-                        int cActual = GetClipboardFormatName(format, szFormatName, sizeof(szFormatName) / sizeof (TCHAR));
-                        if (cActual)
-                        {
-                            if (RTStrCmp(szFormatName, "HTML Format") == 0)
-                                fFormat |= VBOX_SHARED_CLIPBOARD_FMT_HTML;
-#ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
-                            if (   RTStrCmp(szFormatName, CFSTR_FILEDESCRIPTOR) == 0
-                                || RTStrCmp(szFormatName, CFSTR_FILECONTENTS) == 0)
-                                fFormat |= VBOX_SHARED_CLIPBOARD_FMT_URI_LIST;
-#endif
-                        }
-                    }
-                    break;
-            }
+            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
@@ -322,14 +293,14 @@
                 /* Unsupported clipboard format is requested. */
                 LogFunc(("WM_RENDERFORMAT unsupported format requested or client is not active\n"));
-                EmptyClipboard();
+                VBoxClipboardWinClear();
             }
             else
             {
-                int vboxrc = vboxClipboardReadDataFromClient(pCtx, fFormat);
-
-                LogFunc(("vboxClipboardReadDataFromClient vboxrc = %d, pv %p, cb %d, u32Format %d\n",
-                          vboxrc, pCtx->pClient->data.pv, pCtx->pClient->data.cb, pCtx->pClient->data.u32Format));
-
-                if (   RT_SUCCESS (vboxrc)
+                int rc = vboxClipboardReadDataFromClient(pCtx, fFormat);
+
+                LogFunc(("vboxClipboardReadDataFromClient rc = %Rrc, pv %p, cb %d, u32Format %d\n",
+                          rc, pCtx->pClient->data.pv, pCtx->pClient->data.cb, pCtx->pClient->data.u32Format));
+
+                if (   RT_SUCCESS (rc)
                     && pCtx->pClient->data.pv != NULL
                     && pCtx->pClient->data.cb > 0
@@ -367,5 +338,5 @@
                              * size is 'cb' and format is 'format'.
                              */
-                            HANDLE hClip = SetClipboardData(format, hMem);
+                            HANDLE hClip = SetClipboardData(cfFormat, hMem);
 
                             LogFunc(("vboxClipboardHostEvent hClip %p\n", hClip));
@@ -399,19 +370,16 @@
              * windows is to be destroyed and therefore the guest side becomes inactive.
              */
-            int vboxrc = VBoxClipboardWinOpen(hwnd);
-            if (RT_SUCCESS(vboxrc))
+            int rc = VBoxClipboardWinOpen(hwnd);
+            if (RT_SUCCESS(rc))
             {
                 VBoxClipboardWinClear();
                 VBoxClipboardWinClose();
             }
-            else
-            {
-                LogFlowFunc(("WM_RENDERALLFORMATS: error in open clipboard. hwnd: %x, rc: %Rrc\n", hwnd, vboxrc));
-            }
         } break;
 
         case VBOX_CLIPBOARD_WM_SET_FORMATS:
         {
-            if (pCtx->pClient == NULL || pCtx->pClient->fMsgFormats)
+            if (   pCtx->pClient == NULL
+                || pCtx->pClient->fHostMsgFormats)
             {
                 /* Host has pending formats message. Ignore the guest announcement,
@@ -423,39 +391,35 @@
 
             /* Announce available formats. Do not insert data, they will be inserted in WM_RENDER*. */
-            uint32_t u32Formats = (uint32_t)lParam;
-
-            LogFunc(("VBOX_CLIPBOARD_WM_SET_FORMATS: u32Formats=%02X\n", u32Formats));
-
-            int vboxrc = VBoxClipboardWinOpen(hwnd);
-            if (RT_SUCCESS(vboxrc))
+            VBOXCLIPBOARDFORMATS fFormats = (uint32_t)lParam;
+
+            LogFunc(("VBOX_CLIPBOARD_WM_SET_FORMATS: fFormats=%02X\n", fFormats));
+
+            int rc = VBoxClipboardWinOpen(hwnd);
+            if (RT_SUCCESS(rc))
             {
                 VBoxClipboardWinClear();
 
-                LogFunc(("VBOX_CLIPBOARD_WM_SET_FORMATS emptied clipboard\n"));
-
-                HANDLE hClip = NULL;
-
-                if (u32Formats & VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT)
+                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)
+                {
                     hClip = SetClipboardData(CF_UNICODETEXT, NULL);
-
-                if (u32Formats & VBOX_SHARED_CLIPBOARD_FMT_BITMAP)
+                }
+                else if (fFormats & VBOX_SHARED_CLIPBOARD_FMT_BITMAP)
+                {
                     hClip = SetClipboardData(CF_DIB, NULL);
-
-                if (u32Formats & VBOX_SHARED_CLIPBOARD_FMT_HTML)
-                {
-                    UINT format = RegisterClipboardFormat ("HTML Format");
-                    if (format != 0)
-                    {
-                        hClip = SetClipboardData (format, NULL);
-                    }
+                }
+                else if (fFormats & VBOX_SHARED_CLIPBOARD_FMT_HTML)
+                {
+                    cfFormat = RegisterClipboardFormat(VBOX_CLIPBOARD_WIN_REGFMT_HTML);
+                    if (cfFormat)
+                        hClip = SetClipboardData(cfFormat, NULL);
                 }
 
 #ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
-                if (u32Formats & VBOX_SHARED_CLIPBOARD_FMT_URI_LIST)
-                {
-                    UINT format = RegisterClipboardFormat(CFSTR_FILEDESCRIPTOR);
-                    if (format)
-                        hClip = SetClipboardData(format, NULL);
-                }
+                /** @todo */
 #endif
                 VBoxClipboardWinClose();
@@ -480,10 +444,10 @@
         {
             LogFunc(("WM_ %p\n", msg));
-            rc = DefWindowProc(hwnd, msg, wParam, lParam);
-        }
-    }
-
-    LogFunc(("WM_ rc %d\n", rc));
-    return rc;
+            lresultRc = DefWindowProc(hwnd, msg, wParam, lParam);
+        }
+    }
+
+    LogFunc(("WM_ rc %d\n", lresultRc));
+    return lresultRc;
 }
 
@@ -575,5 +539,5 @@
  * @param   pCtx                Clipboard context to synchronize.
  */
-static int vboxClipboardSyncInternal(PVBOXCLIPBOARDCONTEXT pCtx)
+static int vboxClipboardWinSyncInternal(PVBOXCLIPBOARDCONTEXT pCtx)
 {
     AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
@@ -663,5 +627,5 @@
 {
     /* Sync the host clipboard content with the client. */
-    return vboxClipboardSyncInternal(pClient->pCtx);
+    return vboxClipboardWinSyncInternal(pClient->pCtx);
 }
 
@@ -783,5 +747,5 @@
         else if (u32Format & VBOX_SHARED_CLIPBOARD_FMT_HTML)
         {
-            UINT format = RegisterClipboardFormat("HTML Format");
+            UINT format = RegisterClipboardFormat(VBOX_CLIPBOARD_WIN_REGFMT_HTML);
             if (format != 0)
             {
@@ -792,6 +756,5 @@
                     if (lp != NULL)
                     {
-                        LogFunc(("CF_HTML\n"));
-
+                        /** @todo r=andy Add data overflow handling. */
                         vboxClipboardGetData(VBOX_SHARED_CLIPBOARD_FMT_HTML, lp, GlobalSize(hClip),
                                              pv, cb, pcbActual);
@@ -813,139 +776,26 @@
         {
             hClip = GetClipboardData(CF_HDROP);
-            if (hClip != NULL)
+            if (hClip != NULL) /* Do we have data in CF_HDROP format? */
             {
                 LPVOID lp = GlobalLock(hClip);
                 if (lp)
                 {
-                    /* Convert to a string list, separated by \r\n. */
-                    DROPFILES *pDropFiles = (DROPFILES *)hClip;
-                    AssertPtr(pDropFiles);
-
-                    /* Do we need to do Unicode stuff? */
-                    const bool fUnicode = RT_BOOL(pDropFiles->fWide);
-
-                    /* Get the offset of the file list. */
-                    Assert(pDropFiles->pFiles >= sizeof(DROPFILES));
-
-                    /* Note: This is *not* pDropFiles->pFiles! DragQueryFile only
-                     *       will work with the plain storage medium pointer! */
-                    HDROP hDrop = (HDROP)(hClip);
-
-                    /* First, get the file count. */
-                    /** @todo Does this work on Windows 2000 / NT4? */
-                    char *pszFiles = NULL;
-                    uint32_t cchFiles = 0;
-                    UINT cFiles = DragQueryFile(hDrop, UINT32_MAX /* iFile */, NULL /* lpszFile */, 0 /* cchFile */);
-
-                    LogRel(("Shared Clipboard: Got %RU16 file(s), fUnicode=%RTbool\n", cFiles, fUnicode));
-
-                    for (UINT i = 0; i < cFiles; i++)
-                    {
-                        UINT cchFile = DragQueryFile(hDrop, i /* File index */, NULL /* Query size first */, 0 /* cchFile */);
-                        Assert(cchFile);
-
-                        if (RT_FAILURE(rc))
-                            break;
-
-                        char *pszFileUtf8 = NULL; /* UTF-8 version. */
-                        UINT cchFileUtf8 = 0;
-                        if (fUnicode)
-                        {
-                            /* Allocate enough space (including terminator). */
-                            WCHAR *pwszFile = (WCHAR *)RTMemAlloc((cchFile + 1) * sizeof(WCHAR));
-                            if (pwszFile)
-                            {
-                                const UINT cwcFileUtf16 = DragQueryFileW(hDrop, i /* File index */,
-                                                                         pwszFile, cchFile + 1 /* Include terminator */);
-
-                                AssertMsg(cwcFileUtf16 == cchFile, ("cchFileUtf16 (%RU16) does not match cchFile (%RU16)\n",
-                                                                    cwcFileUtf16, cchFile));
-                                RT_NOREF(cwcFileUtf16);
-
-                                rc = RTUtf16ToUtf8(pwszFile, &pszFileUtf8);
-                                if (RT_SUCCESS(rc))
-                                {
-                                    cchFileUtf8 = (UINT)strlen(pszFileUtf8);
-                                    Assert(cchFileUtf8);
-                                }
-
-                                RTMemFree(pwszFile);
-                            }
-                            else
-                                rc = VERR_NO_MEMORY;
-                        }
-                        else /* ANSI */
-                        {
-                            /* Allocate enough space (including terminator). */
-                            pszFileUtf8 = (char *)RTMemAlloc((cchFile + 1) * sizeof(char));
-                            if (pszFileUtf8)
-                            {
-                                cchFileUtf8 = DragQueryFileA(hDrop, i /* File index */,
-                                                             pszFileUtf8, cchFile + 1 /* Include terminator */);
-
-                                AssertMsg(cchFileUtf8 == cchFile, ("cchFileUtf8 (%RU16) does not match cchFile (%RU16)\n",
-                                                                   cchFileUtf8, cchFile));
-                            }
-                            else
-                                rc = VERR_NO_MEMORY;
-                        }
-
-                        if (RT_SUCCESS(rc))
-                        {
-                            LogFlowFunc(("\tFile: %s (cchFile=%RU16)\n", pszFileUtf8, cchFileUtf8));
-
-                            LogRel2(("Shared Clipboard: Adding host file '%s'\n", pszFileUtf8));
-
-                            rc = RTStrAAppendExN(&pszFiles, 1 /* cPairs */, pszFileUtf8, cchFileUtf8);
-                            if (RT_SUCCESS(rc))
-                                cchFiles += cchFileUtf8;
-                        }
-                        else
-                            LogRel(("Shared Clipboard: Error handling file entry #%u, rc=%Rrc\n", i, rc));
-
-                        if (pszFileUtf8)
-                            RTStrFree(pszFileUtf8);
-
-                        if (RT_FAILURE(rc))
-                            break;
-
-                        /* Add separation between filenames.
-                         * Note: Also do this for the last element of the list. */
-                        rc = RTStrAAppendExN(&pszFiles, 1 /* cPairs */, "\r\n", 2 /* Bytes */);
-                        if (RT_SUCCESS(rc))
-                            cchFiles += 2; /* Include \r\n */
-                    }
-
+                    void *pvTemp;
+                    size_t cbTemp;
+                    rc = VBoxClipboardWinDropFilesToStringList((DROPFILES *)lp, &pvTemp, &cbTemp);
                     if (RT_SUCCESS(rc))
                     {
-                        cchFiles += 1; /* Add string termination. */
-                        uint32_t cbFiles = cchFiles * sizeof(char);
-
-                        LogFlowFunc(("cFiles=%u, cchFiles=%RU32, cbFiles=%RU32, pszFiles=0x%p\n",
-                                     cFiles, cchFiles, cbFiles, pszFiles));
-
-                        /* Translate the list into URI elements. */
-                        SharedClipboardURIList lstURI;
-                        rc = lstURI.AppendNativePathsFromList(pszFiles, cbFiles,
-                                                              SHAREDCLIPBOARDURILIST_FLAGS_ABSOLUTE_PATHS);
-                        if (RT_SUCCESS(rc))
+                        if (cbTemp > cb) /** @todo Add overflow handling! */
                         {
-                            RTCString strRoot = lstURI.GetRootEntries();
-                            size_t cbRoot = strRoot.length() + 1; /* Include termination */
-
-                            if (cbRoot > cb) /** @todo Add overflow handling! */
-                                cbRoot = cb; /* Never copy more than the available buffer supplies. */
-
-                            memcpy(pv, strRoot.c_str(), cbRoot);
-
-                            *pcbActual = (uint32_t)cbRoot;
+                            AssertMsgFailed(("More data buffer needed -- fix this\n"));
+                            cbTemp = cb; /* Never copy more than the available buffer supplies. */
                         }
+
+                        memcpy(pv, pvTemp, cbTemp);
+
+                        RTMemFree(pvTemp);
+
+                        *pcbActual = (uint32_t)cbTemp;
                     }
-
-                    LogFlowFunc(("Building CF_HDROP list rc=%Rrc, pszFiles=0x%p, cFiles=%RU16, cchFiles=%RU32\n",
-                                 rc, pszFiles, cFiles, cchFiles));
-
-                    if (pszFiles)
-                        RTStrFree(pszFiles);
 
                     GlobalUnlock(hClip);
@@ -982,9 +832,9 @@
 
         if (   u32Format == VBOX_SHARED_CLIPBOARD_FMT_HTML
-            && !IsWindowsHTML((const char*)pv))
+            && !VBoxClipboardWinIsCFHTML((const char*)pv))
         {
             /* check that this is not already CF_HTML */
             uint32_t cbResult;
-            int rc = ConvertMimeToCFHTML((const char *)pv, cb, &pszResult, &cbResult);
+            int rc = VBoxClipboardWinConvertMIMEToCFHTML((const char *)pv, cb, &pszResult, &cbResult);
             if (RT_SUCCESS(rc))
             {
@@ -1015,227 +865,2 @@
 }
 
-
-/**
- * Extracts field value from CF_HTML struct
- *
- * @returns VBox status code
- * @param   pszSrc      source in CF_HTML format
- * @param   pszOption   Name of CF_HTML field
- * @param   puValue     Where to return extracted value of CF_HTML field
- */
-static int GetHeaderValue(const char *pszSrc, const char *pszOption, uint32_t *puValue)
-{
-    int rc = VERR_INVALID_PARAMETER;
-
-    Assert(pszSrc);
-    Assert(pszOption);
-
-    const char *pszOptionValue = RTStrStr(pszSrc, pszOption);
-    if (pszOptionValue)
-    {
-        size_t cchOption = strlen(pszOption);
-        Assert(cchOption);
-
-        rc = RTStrToUInt32Ex(pszOptionValue + cchOption, NULL, 10, puValue);
-    }
-    return rc;
-}
-
-
-/**
- * Check that the source string contains CF_HTML struct
- *
- * @param   pszSource   source string.
- *
- * @returns @c true if the @a pszSource string is in CF_HTML format
- */
-static bool IsWindowsHTML(const char *pszSource)
-{
-    return    RTStrStr(pszSource, "Version:") != NULL
-           && RTStrStr(pszSource, "StartHTML:") != NULL;
-}
-
-
-/**
- * Converts clipboard data from CF_HTML format to MIME clipboard format.
- *
- * Returns allocated buffer that contains html converted to text/html mime type
- *
- * @returns VBox status code.
- * @param   pszSource   The input.
- * @param   cch         The length of the input.
- * @param   ppszOutput  Where to return the result.  Free using RTMemFree.
- * @param   pcbOutput   Where to the return length of the result (bytes/chars).
- */
-static int ConvertCFHtmlToMime(const char *pszSource, const uint32_t cch, char **ppszOutput, uint32_t *pcbOutput)
-{
-    Assert(pszSource);
-    Assert(cch);
-    Assert(ppszOutput);
-    Assert(pcbOutput);
-
-    uint32_t offStart;
-    int rc = GetHeaderValue(pszSource, "StartFragment:", &offStart);
-    if (RT_SUCCESS(rc))
-    {
-        uint32_t offEnd;
-        rc = GetHeaderValue(pszSource, "EndFragment:", &offEnd);
-        if (RT_SUCCESS(rc))
-        {
-            if (   offStart > 0
-                && offEnd > 0
-                && offEnd > offStart
-                && offEnd <= cch)
-            {
-                uint32_t cchSubStr = offEnd - offStart;
-                char *pszResult = (char *)RTMemAlloc(cchSubStr + 1);
-                if (pszResult)
-                {
-                    rc = RTStrCopyEx(pszResult, cchSubStr + 1, pszSource + offStart, cchSubStr);
-                    if (RT_SUCCESS(rc))
-                    {
-                        *ppszOutput = pszResult;
-                        *pcbOutput  = (uint32_t)(cchSubStr + 1);
-                        rc = VINF_SUCCESS;
-                    }
-                    else
-                    {
-                        LogRelFlowFunc(("Error: Unknown CF_HTML format. Expected EndFragment. rc = %Rrc\n", rc));
-                        RTMemFree(pszResult);
-                    }
-                }
-                else
-                {
-                    LogRelFlowFunc(("Error: Unknown CF_HTML format. Expected EndFragment\n"));
-                    rc = VERR_NO_MEMORY;
-                }
-            }
-            else
-            {
-                LogRelFlowFunc(("Error: CF_HTML out of bounds - offStart=%#x offEnd=%#x cch=%#x\n", offStart, offEnd, cch));
-                rc = VERR_INVALID_PARAMETER;
-            }
-        }
-        else
-        {
-            LogRelFlowFunc(("Error: Unknown CF_HTML format. Expected EndFragment. rc = %Rrc\n", rc));
-            rc = VERR_INVALID_PARAMETER;
-        }
-    }
-    else
-    {
-        LogRelFlowFunc(("Error: Unknown CF_HTML format. Expected StartFragment. rc = %Rrc\n", rc));
-        rc = VERR_INVALID_PARAMETER;
-    }
-
-    return rc;
-}
-
-
-
-/**
- * Converts source UTF-8 MIME HTML clipboard data to UTF-8 CF_HTML format.
- *
- * This is just encapsulation work, slapping a header on the data.
- *
- * It allocates
- *
- * Calculations:
- *   Header length = format Length + (2*(10 - 5('%010d'))('digits')) - 2('%s') = format length + 8
- *   EndHtml       = Header length + fragment length
- *   StartHtml     = 105(constant)
- *   StartFragment = 141(constant) may vary if the header html content will be extended
- *   EndFragment   = Header length + fragment length - 38(ending length)
- *
- * @param   pszSource   Source buffer that contains utf-16 string in mime html format
- * @param   cb          Size of source buffer in bytes
- * @param   ppszOutput  Where to return the allocated output buffer to put converted UTF-8
- *                      CF_HTML clipboard data.  This function allocates memory for this.
- * @param   pcbOutput   Where to return the size of allocated result buffer in bytes/chars, including zero terminator
- *
- * @note    output buffer should be free using RTMemFree()
- * @note    Everything inside of fragment can be UTF8. Windows allows it. Everything in header should be Latin1.
- */
-static int ConvertMimeToCFHTML(const char *pszSource, size_t cb, char **ppszOutput, uint32_t *pcbOutput)
-{
-    Assert(ppszOutput);
-    Assert(pcbOutput);
-    Assert(pszSource);
-    Assert(cb);
-
-    /* construct CF_HTML formatted string */
-    char *pszResult = NULL;
-    size_t cchFragment;
-    int rc = RTStrNLenEx(pszSource, cb, &cchFragment);
-    if (!RT_SUCCESS(rc))
-    {
-        LogRelFlowFunc(("Error: invalid source fragment. rc = %Rrc\n"));
-        return VERR_INVALID_PARAMETER;
-    }
-
-    /*
-    @StartHtml - pos before <html>
-    @EndHtml - whole size of text excluding ending zero char
-    @StartFragment - pos after <!--StartFragment-->
-    @EndFragment - pos before <!--EndFragment-->
-    @note: all values includes CR\LF inserted into text
-    Calculations:
-    Header length = format Length + (3*6('digits')) - 2('%s') = format length + 16 (control value - 183)
-    EndHtml  = Header length + fragment length
-    StartHtml = 105(constant)
-    StartFragment = 143(constant)
-    EndFragment  = Header length + fragment length - 40(ending length)
-    */
-    static const char s_szFormatSample[] =
-    /*   0:   */ "Version:1.0\r\n"
-    /*  13:   */ "StartHTML:000000101\r\n"
-    /*  34:   */ "EndHTML:%0000009u\r\n" // END HTML = Header length + fragment length
-    /*  53:   */ "StartFragment:000000137\r\n"
-    /*  78:   */ "EndFragment:%0000009u\r\n"
-    /* 101:   */ "<html>\r\n"
-    /* 109:   */ "<body>\r\n"
-    /* 117:   */ "<!--StartFragment-->"
-    /* 137:   */ "%s"
-    /* 137+2: */ "<!--EndFragment-->\r\n"
-    /* 157+2: */ "</body>\r\n"
-    /* 166+2: */ "</html>\r\n";
-    /* 175+2: */
-    AssertCompile(sizeof(s_szFormatSample) == 175 + 2 + 1);
-
-    /* calculate parameters of CF_HTML header */
-    size_t cchHeader      = sizeof(s_szFormatSample) - 1;
-    size_t offEndHtml     = cchHeader + cchFragment;
-    size_t offEndFragment = cchHeader + cchFragment - 38; /* 175-137 = 38 */
-    pszResult = (char *)RTMemAlloc(offEndHtml + 1);
-    if (pszResult == NULL)
-    {
-        LogRelFlowFunc(("Error: Cannot allocate memory for result buffer. rc = %Rrc\n"));
-        return VERR_NO_MEMORY;
-    }
-
-    /* format result CF_HTML string */
-    size_t cchFormatted = RTStrPrintf(pszResult, offEndHtml + 1,
-                                      s_szFormatSample, offEndHtml, offEndFragment, pszSource);
-    Assert(offEndHtml == cchFormatted); NOREF(cchFormatted);
-
-#ifdef VBOX_STRICT
-    /* Control calculations. check consistency.*/
-    static const char s_szStartFragment[] = "<!--StartFragment-->";
-    static const char s_szEndFragment[] = "<!--EndFragment-->";
-
-    /* check 'StartFragment:' value */
-    const char *pszRealStartFragment = RTStrStr(pszResult, s_szStartFragment);
-    Assert(&pszRealStartFragment[sizeof(s_szStartFragment) - 1] - pszResult == 137);
-
-    /* check 'EndFragment:' value */
-    const char *pszRealEndFragment = RTStrStr(pszResult, s_szEndFragment);
-    Assert((size_t)(pszRealEndFragment - pszResult) == offEndFragment);
-#endif
-
-    *ppszOutput = pszResult;
-    *pcbOutput = (uint32_t)cchFormatted + 1;
-    Assert(*pcbOutput == cchFormatted + 1);
-
-    return VINF_SUCCESS;
-}
-
Index: /trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc.cpp
===================================================================
--- /trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc.cpp	(revision 78500)
+++ /trunk/src/VBox/HostServices/SharedClipboard/VBoxSharedClipboardSvc.cpp	(revision 78501)
@@ -86,4 +86,7 @@
 
 #include "VBoxClipboard.h"
+#ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
+# include "VBoxSharedClipboardSvc-uri.h"
+#endif
 
 
@@ -200,12 +203,12 @@
 {
     /* Message priority is taken into account. */
-    if (pClient->fMsgQuit)
+    if (pClient->fHostMsgQuit)
     {
         LogFlowFunc(("vboxSvcClipboardReturnMsg: Quit\n"));
         VBoxHGCMParmUInt32Set(&paParms[0], VBOX_SHARED_CLIPBOARD_HOST_MSG_QUIT);
         VBoxHGCMParmUInt32Set(&paParms[1], 0);
-        pClient->fMsgQuit = false;
-    }
-    else if (pClient->fMsgReadData)
+        pClient->fHostMsgQuit = false;
+    }
+    else if (pClient->fHostMsgReadData)
     {
         uint32_t fFormat = 0;
@@ -218,18 +221,25 @@
         else if (pClient->u32RequestedFormat & VBOX_SHARED_CLIPBOARD_FMT_HTML)
             fFormat = VBOX_SHARED_CLIPBOARD_FMT_HTML;
+#ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
+        else if (pClient->u32RequestedFormat & VBOX_SHARED_CLIPBOARD_FMT_URI_LIST)
+            fFormat = VBOX_SHARED_CLIPBOARD_FMT_URI_LIST;
+#endif
         else
-            AssertStmt(pClient->u32RequestedFormat == 0, pClient->u32RequestedFormat = 0);
+        {
+            LogRel2(("Clipboard: Unsupported format from guest (0x%x), skipping\n", fFormat));
+            pClient->u32RequestedFormat = 0;
+        }
         pClient->u32RequestedFormat &= ~fFormat;
         VBoxHGCMParmUInt32Set(&paParms[0], VBOX_SHARED_CLIPBOARD_HOST_MSG_READ_DATA);
         VBoxHGCMParmUInt32Set(&paParms[1], fFormat);
         if (pClient->u32RequestedFormat == 0)
-            pClient->fMsgReadData = false;
-    }
-    else if (pClient->fMsgFormats)
+            pClient->fHostMsgReadData = false;
+    }
+    else if (pClient->fHostMsgFormats)
     {
         LogFlowFunc(("vboxSvcClipboardReturnMsg: Formats %02X\n", pClient->u32AvailableFormats));
         VBoxHGCMParmUInt32Set(&paParms[0], VBOX_SHARED_CLIPBOARD_HOST_MSG_REPORT_FORMATS);
         VBoxHGCMParmUInt32Set(&paParms[1], pClient->u32AvailableFormats);
-        pClient->fMsgFormats = false;
+        pClient->fHostMsgFormats = false;
     }
     else
@@ -255,5 +265,5 @@
             {
                 LogFlowFunc(("Quit\n"));
-                pClient->fMsgQuit = true;
+                pClient->fHostMsgQuit = true;
             } break;
             case VBOX_SHARED_CLIPBOARD_HOST_MSG_READ_DATA:
@@ -268,5 +278,5 @@
                 LogFlowFunc(("ReadData %02X\n", u32Formats));
                 pClient->u32RequestedFormat = u32Formats;
-                pClient->fMsgReadData = true;
+                pClient->fHostMsgReadData = true;
             } break;
             case VBOX_SHARED_CLIPBOARD_HOST_MSG_REPORT_FORMATS:
@@ -281,5 +291,5 @@
                 LogFlowFunc(("Formats %02X\n", u32Formats));
                 pClient->u32AvailableFormats = u32Formats;
-                pClient->fMsgFormats = true;
+                pClient->fHostMsgFormats = true;
             } break;
             default:
@@ -683,5 +693,10 @@
         default:
         {
+#ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
+            rc = vboxClipboardSvcURIHandler(u32ClientID, pvClient, u32Function, cParms, paParms, tsArrival,
+                                            &fAsynchronousProcessing);
+#else
             rc = VERR_NOT_IMPLEMENTED;
+#endif
         }
     }
@@ -772,5 +787,9 @@
 
         default:
-            break;
+        {
+#ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
+            rc = vboxClipboardSvcURIHostHandler(u32Function, cParms, paParms);
+#endif
+        } break;
     }
 
@@ -786,7 +805,7 @@
 {
     SSMFIELD_ENTRY(VBOXCLIPBOARDCLIENTDATA, u32ClientID),  /* for validation purposes */
-    SSMFIELD_ENTRY(VBOXCLIPBOARDCLIENTDATA, fMsgQuit),
-    SSMFIELD_ENTRY(VBOXCLIPBOARDCLIENTDATA, fMsgReadData),
-    SSMFIELD_ENTRY(VBOXCLIPBOARDCLIENTDATA, fMsgFormats),
+    SSMFIELD_ENTRY(VBOXCLIPBOARDCLIENTDATA, fHostMsgQuit),
+    SSMFIELD_ENTRY(VBOXCLIPBOARDCLIENTDATA, fHostMsgReadData),
+    SSMFIELD_ENTRY(VBOXCLIPBOARDCLIENTDATA, fHostMsgFormats),
     SSMFIELD_ENTRY(VBOXCLIPBOARDCLIENTDATA, u32RequestedFormat),
     SSMFIELD_ENTRY_TERM()
@@ -843,7 +862,7 @@
     bool fAsync: 1; /* Guest is waiting for a message. */
 
-    bool fMsgQuit: 1;
-    bool fMsgReadData: 1;
-    bool fMsgFormats: 1;
+    bool fHostMsgQuit: 1;
+    bool fHostMsgReadData: 1;
+    bool fHostMsgFormats: 1;
 
     struct
@@ -918,7 +937,7 @@
         AssertRCReturn(rc, rc);
 
-        pClient->fMsgQuit           = savedState.fMsgQuit;
-        pClient->fMsgReadData       = savedState.fMsgReadData;
-        pClient->fMsgFormats        = savedState.fMsgFormats;
+        pClient->fHostMsgQuit       = savedState.fHostMsgQuit;
+        pClient->fHostMsgReadData   = savedState.fHostMsgReadData;
+        pClient->fHostMsgFormats    = savedState.fHostMsgFormats;
         pClient->u32RequestedFormat = savedState.u32RequestedFormat;
     }
