Index: trunk/src/VBox/Main/Makefile.kmk
===================================================================
--- trunk/src/VBox/Main/Makefile.kmk	(revision 78896)
+++ trunk/src/VBox/Main/Makefile.kmk	(revision 78897)
@@ -136,4 +136,10 @@
 ifdef VBOX_WITH_SDS
 VBOX_MAIN_DEFS += VBOX_WITH_SDS
+endif
+ifdef VBOX_WITH_SHARED_CLIPBOARD
+VBOX_MAIN_DEFS += VBOX_WITH_SHARED_CLIPBOARD
+ if VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
+  VBOX_MAIN_DEFS += VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
+ endif
 endif
 ifdef VBOX_WITH_USB_CARDREADER
@@ -681,4 +687,8 @@
 endif
 
+ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
+ VBoxSVC_SOURCES += $(PATH_ROOT)/src/VBox/GuestHost/SharedClipboard/ClipboardCache.cpp
+endif
+
 $(call KB_FN_DO_PASS0_ON_TARGET,VBoxSVC) # Sets VBoxSVC_0_OUTDIR
 
Index: trunk/src/VBox/Main/idl/VirtualBox.xidl
===================================================================
--- trunk/src/VBox/Main/idl/VirtualBox.xidl	(revision 78896)
+++ trunk/src/VBox/Main/idl/VirtualBox.xidl	(revision 78897)
@@ -4389,5 +4389,5 @@
   <interface
     name="IInternalMachineControl" extends="$unknown"
-    uuid="cdbc59df-4f4d-4cf2-809c-917601355afc"
+    uuid="0075FD6C-00C2-4484-0077-C057003D9C90"
     internal="yes"
     wsmap="suppress"
@@ -4591,5 +4591,74 @@
       </param>
     </method>
-
+    <method name="clipboardAreaRegister">
+      <desc>
+        Registers a new clipboard area.
+      </desc>
+      <param name="parms" type="wstring" dir="in" safearray="yes">
+        <desc>
+          Registration parameters. Currently not used and therefore ignored.
+        </desc>
+      </param>
+      <param name="id" type="unsigned long" dir="out">
+        <desc>
+          Returns the new clipboard area which got registered.
+        </desc>
+      </param>
+    </method>
+    <method name="clipboardAreaUnregister">
+      <desc>
+        Unregisters a formerly registered clipboard area.
+      </desc>
+      <param name="id" type="unsigned long" dir="in">
+        <desc>
+          Clipboard area to unregister.
+        </desc>
+      </param>
+    </method>
+    <method name="clipboardAreaAttach">
+      <desc>
+        Attaches to a registered clipboard area.
+      </desc>
+      <param name="id" type="unsigned long" dir="in">
+        <desc>
+          Clipboard area to attach to.
+        </desc>
+      </param>
+    </method>
+    <method name="clipboardAreaDetach">
+      <desc>
+        Detaches from a registered clipboard area.
+      </desc>
+      <param name="id" type="unsigned long" dir="in">
+        <desc>
+          Clipboard area to detach from.
+        </desc>
+      </param>
+    </method>
+    <method name="clipboardAreaGetMostRecent">
+      <desc>
+        Returns the most recent (last registered) clipboard area.
+      </desc>
+      <param name="id" type="unsigned long" dir="out">
+        <desc>
+          Returns the most recent clipboard area.
+        </desc>
+      </param>
+    </method>
+    <method name="clipboardAreaGetRefCount">
+      <desc>
+        Returns the current reference count of a clipboard area.
+      </desc>
+      <param name="id" type="unsigned long" dir="in">
+        <desc>
+          Clipboard area to return reference count for.
+        </desc>
+      </param>
+      <param name="refcount" type="unsigned long" dir="out">
+        <desc>
+          Returns the current reference count.
+        </desc>
+      </param>
+    </method>
     <method name="pushGuestProperty">
       <desc>
Index: trunk/src/VBox/Main/include/ConsoleImpl.h
===================================================================
--- trunk/src/VBox/Main/include/ConsoleImpl.h	(revision 78896)
+++ trunk/src/VBox/Main/include/ConsoleImpl.h	(revision 78897)
@@ -865,4 +865,12 @@
 #endif
 
+#ifdef VBOX_WITH_SHARED_CLIPBOARD
+    /** @name Shared Clipboard support
+     * @{ */
+    static DECLCALLBACK(int) i_sharedClipboardServiceCallback(void *pvExtension, uint32_t u32Function,
+                                                              void *pvParms, uint32_t cbParms);
+    /** @} */
+#endif /* VBOX_WITH_SHARED_CLIPBOARD_URI_LIST */
+
     /** @name Disk encryption support
      * @{ */
Index: trunk/src/VBox/Main/include/ConsoleVRDPServer.h
===================================================================
--- trunk/src/VBox/Main/include/ConsoleVRDPServer.h	(revision 78896)
+++ trunk/src/VBox/Main/include/ConsoleVRDPServer.h	(revision 78897)
@@ -139,4 +139,6 @@
     void SendAudioVolume (uint16_t left, uint16_t right) const;
     void SendUSBRequest (uint32_t u32ClientId, void *pvParms, uint32_t cbParms) const;
+    void SendClipboard (uint32_t u32Function, uint32_t u32Format,
+                        void *pvData, uint32_t cbData, uint32_t *pcbActualRead) const;
 
     void QueryInfo (uint32_t index, void *pvBuffer, uint32_t cbBuffer, uint32_t *pcbOut) const;
@@ -220,9 +222,7 @@
 
     int mcClipboardRefs;
-    HGCMSVCEXTHANDLE mhClipboard;
     PFNVRDPCLIPBOARDEXTCALLBACK mpfnClipboardCallback;
 
     static DECLCALLBACK(int) ClipboardCallback (void *pvCallback, uint32_t u32ClientId, uint32_t u32Function, uint32_t u32Format, const void *pvData, uint32_t cbData);
-    static DECLCALLBACK(int) ClipboardServiceExtension (void *pvExtension, uint32_t u32Function, void *pvParm, uint32_t cbParms);
 
 #ifdef VBOX_WITH_USB
Index: trunk/src/VBox/Main/include/MachineImpl.h
===================================================================
--- trunk/src/VBox/Main/include/MachineImpl.h	(revision 78896)
+++ trunk/src/VBox/Main/include/MachineImpl.h	(revision 78897)
@@ -1228,4 +1228,10 @@
                          ComPtr<IProgress> &aProgress);
     HRESULT finishOnlineMergeMedium();
+    HRESULT clipboardAreaRegister(const std::vector<com::Utf8Str> &aParms, ULONG *aID);
+    HRESULT clipboardAreaUnregister(ULONG aID);
+    HRESULT clipboardAreaAttach(ULONG aID);
+    HRESULT clipboardAreaDetach(ULONG aID);
+    HRESULT clipboardAreaGetMostRecent(ULONG *aID);
+    HRESULT clipboardAreaGetRefCount(ULONG aID, ULONG *aRefCount);
     HRESULT pullGuestProperties(std::vector<com::Utf8Str> &aNames,
                                 std::vector<com::Utf8Str> &aValues,
@@ -1383,4 +1389,10 @@
                          ComPtr<IProgress> &aProgress);
     HRESULT finishOnlineMergeMedium();
+    HRESULT clipboardAreaRegister(const std::vector<com::Utf8Str> &aParms, ULONG *aID);
+    HRESULT clipboardAreaUnregister(ULONG aID);
+    HRESULT clipboardAreaAttach(ULONG aID);
+    HRESULT clipboardAreaDetach(ULONG aID);
+    HRESULT clipboardAreaGetMostRecent(ULONG *aID);
+    HRESULT clipboardAreaGetRefCount(ULONG aID, ULONG *aRefCount);
     HRESULT pullGuestProperties(std::vector<com::Utf8Str> &aNames,
                                 std::vector<com::Utf8Str> &aValues,
Index: trunk/src/VBox/Main/include/VirtualBoxImpl.h
===================================================================
--- trunk/src/VBox/Main/include/VirtualBoxImpl.h	(revision 78896)
+++ trunk/src/VBox/Main/include/VirtualBoxImpl.h	(revision 78897)
@@ -72,4 +72,7 @@
 #endif
 
+#ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
+struct SharedClipboardAreaData;
+#endif
 
 class ATL_NO_VTABLE VirtualBox :
@@ -170,4 +173,16 @@
     void i_onSnapshotRestored(const Guid &aMachineId, const Guid &aSnapshotId);
     void i_onSnapshotChange(const Guid &aMachineId, const Guid &aSnapshotId);
+
+#ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
+    int i_onClipboardAreaCreate(SharedClipboardAreaData &AreaData, uint32_t fFlags);
+    int i_onClipboardAreaDestroy(SharedClipboardAreaData &AreaData);
+    int i_onClipboardAreaRegister(const std::vector<com::Utf8Str> &aParms, ULONG *aID);
+    int i_onClipboardAreaUnregister(ULONG aID);
+    int i_onClipboardAreaAttach(ULONG aID);
+    int i_onClipboardAreaDetach(ULONG aID);
+    ULONG i_onClipboardAreaGetMostRecent(void);
+    ULONG i_onClipboardAreaGetRefCount(ULONG aID);
+#endif /* VBOX_WITH_SHARED_CLIPBOARD_URI_LIST */
+
     void i_onGuestPropertyChange(const Guid &aMachineId, IN_BSTR aName, IN_BSTR aValue,
                                  IN_BSTR aFlags);
Index: trunk/src/VBox/Main/src-client/ConsoleImpl.cpp
===================================================================
--- trunk/src/VBox/Main/src-client/ConsoleImpl.cpp	(revision 78896)
+++ trunk/src/VBox/Main/src-client/ConsoleImpl.cpp	(revision 78897)
@@ -126,5 +126,10 @@
 #include <VBox/VMMDev.h>
 
+#ifdef VBOX_WITH_SHARED_CLIPBOARD
 #include <VBox/HostServices/VBoxClipboardSvc.h>
+# ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
+#  include "SharedClipboardPrivate.h"
+# endif
+#endif
 #include <VBox/HostServices/DragAndDropSvc.h>
 #ifdef VBOX_WITH_GUEST_PROPS
@@ -2085,5 +2090,9 @@
 HRESULT Console::setUseHostClipboard(BOOL aUseHostClipboard)
 {
-    mfUseHostClipboard = !!aUseHostClipboard;
+    if (mfUseHostClipboard != RT_BOOL(aUseHostClipboard))
+    {
+        mfUseHostClipboard = RT_BOOL(aUseHostClipboard);
+        LogRel(("Shared Clipboard: %s using host clipboard\n", mfUseHostClipboard ? "Enabled" : "Disabled"));
+    }
 
     return S_OK;
@@ -8399,4 +8408,127 @@
 }
 
+#ifdef VBOX_WITH_SHARED_CLIPBOARD
+/* static */
+DECLCALLBACK(int) Console::i_sharedClipboardServiceCallback(void *pvExtension, uint32_t u32Function,
+                                                            void *pvParms, uint32_t cbParms)
+{
+    LogFlowFunc(("pvExtension=%p, u32Function=%RU32, pvParms=%p, cbParms=%RU32\n",
+                 pvExtension, u32Function, pvParms, cbParms));
+
+    RT_NOREF(pvParms, cbParms);
+
+    Console *pThis = reinterpret_cast<Console *>(pvExtension);
+    AssertPtrReturn(pThis, VERR_INVALID_POINTER);
+
+    ComPtr<IInternalMachineControl> pControl = pThis->mControl;
+
+    int rc = VINF_SUCCESS;
+    HRESULT hrc;
+
+#define H()         AssertMsgBreakStmt(!FAILED(hrc), ("hrc=%Rhrc\n", hrc), rc = VERR_GENERAL_FAILURE)
+
+    switch (u32Function)
+    {
+        case VBOX_CLIPBOARD_EXT_FN_SET_CALLBACK:
+        {
+            LogFlowFunc(("VBOX_CLIPBOARD_EXT_FN_SET_CALLBACK\n"));
+        } break;
+
+        case VBOX_CLIPBOARD_EXT_FN_FORMAT_ANNOUNCE:
+        {
+            LogFlowFunc(("VBOX_CLIPBOARD_EXT_FN_FORMAT_ANNOUNCE\n"));
+
+            VBOXCLIPBOARDEXTPARMS *pParms = (VBOXCLIPBOARDEXTPARMS *)pvParms;
+
+            /* The guest announces clipboard formats. This must be delivered to all clients. */
+            if (pThis->mConsoleVRDPServer)
+                pThis->mConsoleVRDPServer->SendClipboard(VRDE_CLIPBOARD_FUNCTION_FORMAT_ANNOUNCE,
+                                                         pParms->u32Format,
+                                                         NULL,
+                                                         0,
+                                                         NULL);
+        } break;
+
+        case VBOX_CLIPBOARD_EXT_FN_DATA_READ:
+        {
+            LogFlowFunc(("VBOX_CLIPBOARD_EXT_FN_DATA_READ\n"));
+
+            VBOXCLIPBOARDEXTPARMS *pParms = (VBOXCLIPBOARDEXTPARMS *)pvParms;
+
+            /* The clipboard service expects that the pvData buffer will be filled
+             * with clipboard data. The server returns the data from the client that
+             * announced the requested format most recently.
+             */
+            if (pThis->mConsoleVRDPServer)
+                pThis->mConsoleVRDPServer->SendClipboard(VRDE_CLIPBOARD_FUNCTION_DATA_READ,
+                                                         pParms->u32Format,
+                                                         pParms->u.pvData,
+                                                         pParms->cbData,
+                                                         &pParms->cbData);
+        } break;
+
+        case VBOX_CLIPBOARD_EXT_FN_DATA_WRITE:
+        {
+            LogFlowFunc(("VBOX_CLIPBOARD_EXT_FN_DATA_WRITE\n"));
+
+            VBOXCLIPBOARDEXTPARMS *pParms = (VBOXCLIPBOARDEXTPARMS *)pvParms;
+
+            if (pThis->mConsoleVRDPServer)
+                pThis->mConsoleVRDPServer->SendClipboard(VRDE_CLIPBOARD_FUNCTION_DATA_WRITE,
+                                                         pParms->u32Format,
+                                                         pParms->u.pvData,
+                                                         pParms->cbData,
+                                                         NULL);
+        } break;
+
+#ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
+        case VBOX_CLIPBOARD_EXT_FN_AREA_REGISTER:
+        {
+            com::SafeArray<BSTR> abstrParms; /* Empty for now. */
+            ULONG uID;
+            hrc = pControl->ClipboardAreaRegister(ComSafeArrayAsInParam(abstrParms), &uID);      H();
+        } break;
+
+        case VBOX_CLIPBOARD_EXT_FN_AREA_UNREGISTER:
+        {
+            PVBOXCLIPBOARDEXTAREAPARMS pParms = (PVBOXCLIPBOARDEXTAREAPARMS)pvParms;
+            AssertPtrBreakStmt(pParms, rc = VERR_INVALID_POINTER);
+            hrc = pControl->ClipboardAreaUnregister(pParms->uID);                                H();
+        } break;
+
+        case VBOX_CLIPBOARD_EXT_FN_AREA_ATTACH:
+        {
+            PVBOXCLIPBOARDEXTAREAPARMS pParms = (PVBOXCLIPBOARDEXTAREAPARMS)pvParms;
+            AssertPtrBreakStmt(pParms, rc = VERR_INVALID_POINTER);
+            hrc = pControl->ClipboardAreaAttach(pParms->uID);                                    H();
+        } break;
+
+        case VBOX_CLIPBOARD_EXT_FN_AREA_DETACH:
+        {
+            PVBOXCLIPBOARDEXTAREAPARMS pParms = (PVBOXCLIPBOARDEXTAREAPARMS)pvParms;
+            AssertPtrBreakStmt(pParms, rc = VERR_INVALID_POINTER);
+            hrc = pControl->ClipboardAreaDetach(pParms->uID);                                    H();
+        } break;
+#endif /* VBOX_WITH_SHARED_CLIPBOARD_URI_LIST */
+
+        default:
+        {
+            rc = VERR_NOT_SUPPORTED;
+        } break;
+    }
+
+#ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST_DISABLED
+    int rc2 = SharedClipboard::hostServiceCallback(SHAREDCLIPBOARDINST(), u32Function, pvParms, cbParms);
+    if (RT_SUCCESS(rc))
+        rc = rc2;
+#endif
+
+#undef H
+
+    LogFlowFuncLeaveRC(rc);
+    return rc;
+}
+#endif /* VBOX_WITH_SHARED_CLIPBOARD */
+
 /**
  * Searches for a shared folder with the given logical name
@@ -9124,5 +9256,5 @@
 {
     VMMDev *pVMMDev = m_pVMMDev;
-    AssertPtr(pVMMDev);
+    AssertPtrReturn(pVMMDev, VERR_INVALID_POINTER);
 
     VBOXHGCMSVCPARM parm;
@@ -9133,24 +9265,24 @@
         default:
         case ClipboardMode_Disabled:
-            LogRel(("Shared clipboard mode: Off\n"));
+            LogRel(("Shared Clipboard: Mode: Off\n"));
             parm.u.uint32 = VBOX_SHARED_CLIPBOARD_MODE_OFF;
             break;
         case ClipboardMode_GuestToHost:
-            LogRel(("Shared clipboard mode: Guest to Host\n"));
+            LogRel(("Shared Clipboard: Mode: Guest to Host\n"));
             parm.u.uint32 = VBOX_SHARED_CLIPBOARD_MODE_GUEST_TO_HOST;
             break;
         case ClipboardMode_HostToGuest:
-            LogRel(("Shared clipboard mode: Host to Guest\n"));
+            LogRel(("Shared Clipboard: Mode: Host to Guest\n"));
             parm.u.uint32 = VBOX_SHARED_CLIPBOARD_MODE_HOST_TO_GUEST;
             break;
         case ClipboardMode_Bidirectional:
-            LogRel(("Shared clipboard mode: Bidirectional\n"));
+            LogRel(("Shared Clipboard: Mode: Bidirectional\n"));
             parm.u.uint32 = VBOX_SHARED_CLIPBOARD_MODE_BIDIRECTIONAL;
             break;
     }
 
-    int rc =  pVMMDev->hgcmHostCall("VBoxSharedClipboard", VBOX_SHARED_CLIPBOARD_HOST_FN_SET_MODE, 1, &parm);
+    int rc = pVMMDev->hgcmHostCall("VBoxSharedClipboard", VBOX_SHARED_CLIPBOARD_HOST_FN_SET_MODE, 1, &parm);
     if (RT_FAILURE(rc))
-        LogRel(("Error changing shared clipboard mode: %Rrc\n", rc));
+        LogRel(("Shared Clipboard: Error changing mode: %Rrc\n", rc));
 
     return rc;
Index: trunk/src/VBox/Main/src-client/ConsoleImpl2.cpp
===================================================================
--- trunk/src/VBox/Main/src-client/ConsoleImpl2.cpp	(revision 78896)
+++ trunk/src/VBox/Main/src-client/ConsoleImpl2.cpp	(revision 78897)
@@ -3085,27 +3085,29 @@
          */
         {
-            /* Load the service */
-            rc = pVMMDev->hgcmLoadService("VBoxSharedClipboard", "VBoxSharedClipboard");
-            if (RT_SUCCESS(rc))
-            {
-                SharedClipboard *pSharedClipboard = SharedClipboard::createInstance(this /* pConsole */);
-                if (pSharedClipboard)
-                {
-# ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST_DISABLED
+            if (SharedClipboard::createInstance(this /* pConsole */) == NULL)
+            {
+                rc = VERR_NO_MEMORY;
+            }
+            else
+            {
+                /* Load the service */
+                rc = pVMMDev->hgcmLoadService("VBoxSharedClipboard", "VBoxSharedClipboard");
+                if (RT_SUCCESS(rc))
+                {
+                    LogRel(("Shared Clipboard: Service loaded\n"));
                     HGCMSVCEXTHANDLE hDummy;
                     rc = HGCMHostRegisterServiceExtension(&hDummy, "VBoxSharedClipboard",
-                                                          &SharedClipboard::hostServiceCallback,
-                                                          pSharedClipboard);
+                                                          &Console::i_sharedClipboardServiceCallback,
+                                                          this /* pvExtension */);
                     if (RT_FAILURE(rc))
+                    {
                         LogRel(("Shared Clipboard: Cannot register service extension, rc=%Rrc\n", rc));
-# endif /* VBOX_WITH_SHARED_CLIPBOARD_URI_LIST */
-
-                    if (RT_SUCCESS(rc))
+                    }
+                    else
                     {
-                        LogRel(("Shared Clipboard: Service loaded\n"));
-
                         /* Set initial clipboard mode. */
                         ClipboardMode_T mode = ClipboardMode_Disabled;
                         hrc = pMachine->COMGETTER(ClipboardMode)(&mode); H();
+
                         rc = i_changeClipboardMode(mode);
                         if (RT_SUCCESS(rc))
@@ -3114,5 +3116,5 @@
                             VBOXHGCMSVCPARM parm;
                             HGCMSvcSetU32(&parm, !i_useHostClipboard());
-                            rc = pSharedClipboard->hostCall(VBOX_SHARED_CLIPBOARD_HOST_FN_SET_HEADLESS, 1, &parm);
+                            rc = SHAREDCLIPBOARDINST()->hostCall(VBOX_SHARED_CLIPBOARD_HOST_FN_SET_HEADLESS, 1, &parm);
                             if (RT_FAILURE(rc))
                                 LogRel(("Shared Clipboard: Unable to set initial headless mode, rc=%Rrc\n", rc));
@@ -3120,6 +3122,4 @@
                     }
                 }
-                else
-                    rc = VERR_NO_MEMORY;
             }
 
Index: trunk/src/VBox/Main/src-client/ConsoleVRDPServer.cpp
===================================================================
--- trunk/src/VBox/Main/src-client/ConsoleVRDPServer.cpp	(revision 78896)
+++ trunk/src/VBox/Main/src-client/ConsoleVRDPServer.cpp	(revision 78897)
@@ -3300,5 +3300,5 @@
     ConsoleVRDPServer *pServer = static_cast <ConsoleVRDPServer *>(pvCallback);
 
-    NOREF(u32ClientId);
+    RT_NOREF(u32ClientId);
 
     switch (u32Function)
@@ -3327,5 +3327,7 @@
 
         default:
+        {
             rc = VERR_NOT_SUPPORTED;
+        } break;
     }
 
@@ -3333,93 +3335,13 @@
 }
 
-DECLCALLBACK(int) ConsoleVRDPServer::ClipboardServiceExtension(void *pvExtension,
-                                                               uint32_t u32Function,
-                                                               void *pvParms,
-                                                               uint32_t cbParms)
-{
-    RT_NOREF(cbParms);
-    LogFlowFunc(("pvExtension = %p, u32Function = %d, pvParms = %p, cbParms = %d\n",
-                 pvExtension, u32Function, pvParms, cbParms));
-
-    int rc = VINF_SUCCESS;
-
-    ConsoleVRDPServer *pServer = static_cast <ConsoleVRDPServer *>(pvExtension);
-
-    VBOXCLIPBOARDEXTPARMS *pParms = (VBOXCLIPBOARDEXTPARMS *)pvParms;
-
-    switch (u32Function)
-    {
-        case VBOX_CLIPBOARD_EXT_FN_SET_CALLBACK:
-        {
-            pServer->mpfnClipboardCallback = pParms->u.pfnCallback;
-        } break;
-
-        case VBOX_CLIPBOARD_EXT_FN_FORMAT_ANNOUNCE:
-        {
-            /* The guest announces clipboard formats. This must be delivered to all clients. */
-            if (mpEntryPoints && pServer->mhServer)
-            {
-                mpEntryPoints->VRDEClipboard(pServer->mhServer,
-                                             VRDE_CLIPBOARD_FUNCTION_FORMAT_ANNOUNCE,
-                                             pParms->u32Format,
-                                             NULL,
-                                             0,
-                                             NULL);
-            }
-        } break;
-
-        case VBOX_CLIPBOARD_EXT_FN_DATA_READ:
-        {
-            /* The clipboard service expects that the pvData buffer will be filled
-             * with clipboard data. The server returns the data from the client that
-             * announced the requested format most recently.
-             */
-            if (mpEntryPoints && pServer->mhServer)
-            {
-                mpEntryPoints->VRDEClipboard(pServer->mhServer,
-                                             VRDE_CLIPBOARD_FUNCTION_DATA_READ,
-                                             pParms->u32Format,
-                                             pParms->u.pvData,
-                                             pParms->cbData,
-                                             &pParms->cbData);
-            }
-        } break;
-
-        case VBOX_CLIPBOARD_EXT_FN_DATA_WRITE:
-        {
-            if (mpEntryPoints && pServer->mhServer)
-            {
-                mpEntryPoints->VRDEClipboard(pServer->mhServer,
-                                             VRDE_CLIPBOARD_FUNCTION_DATA_WRITE,
-                                             pParms->u32Format,
-                                             pParms->u.pvData,
-                                             pParms->cbData,
-                                             NULL);
-            }
-        } break;
-
-        default:
-            rc = VERR_NOT_SUPPORTED;
-    }
-
-    return rc;
-}
-
 void ConsoleVRDPServer::ClipboardCreate(uint32_t u32ClientId)
 {
     RT_NOREF(u32ClientId);
+
     int rc = lockConsoleVRDPServer();
-
     if (RT_SUCCESS(rc))
     {
         if (mcClipboardRefs == 0)
-        {
-            rc = HGCMHostRegisterServiceExtension(&mhClipboard, "VBoxSharedClipboard", ClipboardServiceExtension, this);
-
-            if (RT_SUCCESS(rc))
-            {
-                mcClipboardRefs++;
-            }
-        }
+            mcClipboardRefs++;
 
         unlockConsoleVRDPServer();
@@ -3430,14 +3352,10 @@
 {
     RT_NOREF(u32ClientId);
+
     int rc = lockConsoleVRDPServer();
-
     if (RT_SUCCESS(rc))
     {
+        Assert(mcClipboardRefs);
         mcClipboardRefs--;
-
-        if (mcClipboardRefs == 0)
-        {
-            HGCMHostUnregisterServiceExtension(mhClipboard);
-        }
 
         unlockConsoleVRDPServer();
@@ -3753,4 +3671,13 @@
     {
         mpEntryPoints->VRDEUSBRequest(mhServer, u32ClientId, pvParms, cbParms);
+    }
+}
+
+void ConsoleVRDPServer::SendClipboard(uint32_t u32Function, uint32_t u32Format,
+                                      void *pvData, uint32_t cbData, uint32_t *pcbActualRead) const
+{
+    if (mpEntryPoints && mhServer)
+    {
+        mpEntryPoints->VRDEClipboard(mhServer, u32Function, u32Format, pvData, cbData, pcbActualRead);
     }
 }
Index: trunk/src/VBox/Main/src-client/SharedClipboardPrivate.cpp
===================================================================
--- trunk/src/VBox/Main/src-client/SharedClipboardPrivate.cpp	(revision 78896)
+++ trunk/src/VBox/Main/src-client/SharedClipboardPrivate.cpp	(revision 78897)
@@ -61,15 +61,8 @@
     RT_NOREF(pvParms, cbParms);
 
-    SharedClipboard *pSharedClipboard = reinterpret_cast<SharedClipboard *>(pvExtension);
-    AssertPtrReturn(pSharedClipboard, VERR_INVALID_POINTER);
+    SharedClipboard *pThis = reinterpret_cast<SharedClipboard *>(pvExtension);
+    AssertPtrReturn(pThis, VERR_INVALID_POINTER);
 
-    int rc;
-
-    switch (u32Function)
-    {
-        default:
-            rc = VERR_NOT_SUPPORTED;
-            break;
-    }
+    int rc = VINF_SUCCESS;
 
     LogFlowFuncLeaveRC(rc);
Index: trunk/src/VBox/Main/src-server/MachineImpl.cpp
===================================================================
--- trunk/src/VBox/Main/src-server/MachineImpl.cpp	(revision 78896)
+++ trunk/src/VBox/Main/src-server/MachineImpl.cpp	(revision 78897)
@@ -13556,4 +13556,77 @@
 }
 
+HRESULT SessionMachine::clipboardAreaRegister(const std::vector<com::Utf8Str> &aParms, ULONG *aID)
+{
+#ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
+    ULONG uID;
+    int rc = mParent->i_onClipboardAreaRegister(aParms, &uID);
+    if (RT_SUCCESS(rc))
+    {
+        if (aID)
+            *aID = uID;
+        return S_OK;
+    }
+    return E_FAIL;
+#else
+    RT_NOREF(aParms, aID);
+    ReturnComNotImplemented();
+#endif
+}
+
+HRESULT SessionMachine::clipboardAreaUnregister(ULONG aID)
+{
+#ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
+    return mParent->i_onClipboardAreaUnregister(aID);
+#else
+    RT_NOREF(aID);
+    ReturnComNotImplemented();
+#endif
+}
+
+HRESULT SessionMachine::clipboardAreaAttach(ULONG aID)
+{
+#ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
+    return mParent->i_onClipboardAreaAttach(aID);
+#else
+    RT_NOREF(aID);
+    ReturnComNotImplemented();
+#endif
+}
+HRESULT SessionMachine::clipboardAreaDetach(ULONG aID)
+{
+#ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
+    return mParent->i_onClipboardAreaDetach(aID);
+#else
+    RT_NOREF(aID);
+    ReturnComNotImplemented();
+#endif
+}
+
+HRESULT SessionMachine::clipboardAreaGetMostRecent(ULONG *aID)
+{
+#ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
+    ULONG uID = mParent->i_onClipboardAreaGetMostRecent();
+    if (aID)
+        *aID = uID;
+    return S_OK;
+#else
+    RT_NOREF(aID);
+    ReturnComNotImplemented();
+#endif
+}
+
+HRESULT SessionMachine::clipboardAreaGetRefCount(ULONG aID, ULONG *aRefCount)
+{
+#ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
+    ULONG uRefCount = mParent->i_onClipboardAreaGetRefCount(aID);
+    if (aRefCount)
+        *aRefCount = uRefCount;
+    return S_OK;
+#else
+    RT_NOREF(aID, aRefCount);
+    ReturnComNotImplemented();
+#endif
+}
+
 HRESULT SessionMachine::pullGuestProperties(std::vector<com::Utf8Str> &aNames,
                                             std::vector<com::Utf8Str> &aValues,
@@ -15042,4 +15115,39 @@
 }
 
+HRESULT Machine::clipboardAreaRegister(const std::vector<com::Utf8Str> &aParms, ULONG *aID)
+{
+    RT_NOREF(aParms, aID);
+    ReturnComNotImplemented();
+}
+
+HRESULT Machine::clipboardAreaUnregister(ULONG aID)
+{
+    RT_NOREF(aID);
+    ReturnComNotImplemented();
+}
+
+HRESULT Machine::clipboardAreaAttach(ULONG aID)
+{
+    RT_NOREF(aID);
+    ReturnComNotImplemented();
+}
+HRESULT Machine::clipboardAreaDetach(ULONG aID)
+{
+    RT_NOREF(aID);
+    ReturnComNotImplemented();
+}
+
+HRESULT Machine::clipboardAreaGetMostRecent(ULONG *aID)
+{
+    RT_NOREF(aID);
+    ReturnComNotImplemented();
+}
+
+HRESULT Machine::clipboardAreaGetRefCount(ULONG aID, ULONG *aRefCount)
+{
+    RT_NOREF(aID, aRefCount);
+    ReturnComNotImplemented();
+}
+
 HRESULT Machine::pullGuestProperties(std::vector<com::Utf8Str> &aNames,
                                      std::vector<com::Utf8Str> &aValues,
Index: trunk/src/VBox/Main/src-server/VirtualBoxImpl.cpp
===================================================================
--- trunk/src/VBox/Main/src-server/VirtualBoxImpl.cpp	(revision 78896)
+++ trunk/src/VBox/Main/src-server/VirtualBoxImpl.cpp	(revision 78897)
@@ -45,4 +45,8 @@
 #include <VBox/settings.h>
 #include <VBox/version.h>
+
+#ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
+# include <VBox/GuestHost/SharedClipboard-uri.h>
+#endif
 
 #include <package-generated.h>
@@ -219,4 +223,42 @@
 typedef std::map<Guid, ComObjPtr<Medium> > HardDiskMap;
 
+#ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
+/**
+ * Structure for keeping Shared Clipboard area data within the VirtualBox object.
+ */
+struct SharedClipboardAreaData
+{
+    SharedClipboardAreaData()
+        : uID(0) { }
+
+    /** The area's (unique) ID. */
+    ULONG               uID;
+    /** The actual Shared Clipboard area assigned to this ID. */
+    SharedClipboardArea Area;
+};
+
+/** Map of Shared Clipboard areas. The key defines the area ID. */
+typedef std::map<ULONG, SharedClipboardAreaData> SharedClipboardAreaMap;
+
+/**
+ * Structure for keeping global Shared Clipboard data within the VirtualBox object.
+ */
+struct SharedClipboardData
+{
+    SharedClipboardData()
+        : uNextClipboardAreaID(0)
+        , uMaxClipboardAreas(32) { }
+
+    /** Critical section to serialize access. */
+    RTCRITSECT                          CritSect;
+    /** The next (free) clipboard area ID. */
+    ULONG                               uNextClipboardAreaID;
+    /** Maximum of concurrent clipboard areas.
+     *  @todo Make this configurable. */
+    ULONG                               uMaxClipboardAreas;
+    /** Map of clipboard areas. The key is the area ID. */
+    SharedClipboardAreaMap              mapClipboardAreas;
+};
+#endif /* VBOX_WITH_SHARED_CLIPBOARD_URI_LIST */
 
 /**
@@ -366,4 +408,9 @@
     bool                                fWatcherIsReliable;
 #endif
+
+#ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
+    /** Data related to Shared Clipboard handling. */
+    SharedClipboardData                 SharedClipboard;
+#endif
 };
 
@@ -3285,4 +3332,184 @@
 };
 
+#ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
+int VirtualBox::i_onClipboardAreaCreate(SharedClipboardAreaData &AreaData, uint32_t fFlags)
+{
+    RT_NOREF(fFlags);
+    int rc = AreaData.Area.OpenTemp(AreaData.uID);
+    LogFlowFunc(("uID=%RU32, rc=%Rrc\n", AreaData.uID, rc));
+    return rc;
+}
+
+int VirtualBox::i_onClipboardAreaDestroy(SharedClipboardAreaData &AreaData)
+{
+    /** @todo Do we need a worker for this to not block here for too long?
+     *        This could take a while to clean up huge areas ... */
+    int rc = AreaData.Area.Close();
+    LogFlowFunc(("uID=%RU32, rc=%Rrc\n", AreaData.uID, rc));
+    return rc;
+}
+
+int VirtualBox::i_onClipboardAreaRegister(const std::vector<com::Utf8Str> &aParms, ULONG *aID)
+{
+    RT_NOREF(aParms);
+    int rc = RTCritSectEnter(&m->SharedClipboard.CritSect);
+    if (RT_SUCCESS(rc))
+    {
+        try
+        {
+            if (m->SharedClipboard.mapClipboardAreas.size() >= m->SharedClipboard.uMaxClipboardAreas)
+            {
+                const ULONG uAreaID = m->SharedClipboard.uNextClipboardAreaID;
+
+                SharedClipboardAreaData AreaData;
+                AreaData.uID = uAreaID;
+
+                rc = i_onClipboardAreaCreate(AreaData, 0 /* fFlags */);
+                if (RT_SUCCESS(rc))
+                {
+                    m->SharedClipboard.mapClipboardAreas[uAreaID] = AreaData;
+                    m->SharedClipboard.uNextClipboardAreaID++;
+
+                    /** @todo Implement collision detection / wrap-around. */
+
+                    if (aID)
+                        *aID = uAreaID;
+
+                    LogThisFunc(("Registered new clipboard area %RU32: '%s'\n",
+                                 uAreaID, AreaData.Area.GetDirAbs()));
+                }
+                else
+                    LogRel(("Clipboard: Failed to create new clipboard area %RU32, rc=%Rrc\n", uAreaID, rc));
+            }
+            else
+            {
+                LogThisFunc(("Maximum number of conucurrent clipboard areas reached (%RU32)\n",
+                             m->SharedClipboard.uMaxClipboardAreas));
+                rc = VERR_TOO_MUCH_DATA; /** @todo Find a better rc. */
+            }
+        }
+        catch (std::bad_alloc &ba)
+        {
+            rc = VERR_NO_MEMORY;
+            RT_NOREF(ba);
+        }
+
+        RTCritSectLeave(&m->SharedClipboard.CritSect);
+    }
+    LogFlowThisFunc(("rc=%Rrc\n", rc));
+    return rc;
+}
+
+int VirtualBox::i_onClipboardAreaUnregister(ULONG aID)
+{
+    RT_NOREF(aID);
+
+    int rc = RTCritSectEnter(&m->SharedClipboard.CritSect);
+    if (RT_SUCCESS(rc))
+    {
+        SharedClipboardAreaMap::iterator itArea = m->SharedClipboard.mapClipboardAreas.find(aID);
+        if (itArea != m->SharedClipboard.mapClipboardAreas.end())
+        {
+            if (itArea->second.Area.GetRefCount() == 0)
+            {
+                rc = i_onClipboardAreaDestroy(itArea->second);
+                if (RT_SUCCESS(rc))
+                {
+                    m->SharedClipboard.mapClipboardAreas.erase(itArea);
+                }
+            }
+            else
+                rc = VERR_WRONG_ORDER;
+        }
+        else
+            rc = VERR_NOT_FOUND;
+
+        int rc2 = RTCritSectLeave(&m->SharedClipboard.CritSect);
+        AssertRC(rc2);
+    }
+    LogFlowThisFunc(("aID=%RU32, rc=%Rrc\n", aID, rc));
+    return rc;
+}
+
+int VirtualBox::i_onClipboardAreaAttach(ULONG aID)
+{
+    int rc = RTCritSectEnter(&m->SharedClipboard.CritSect);
+    if (RT_SUCCESS(rc))
+    {
+        SharedClipboardAreaMap::iterator itArea = m->SharedClipboard.mapClipboardAreas.find(aID);
+        if (itArea != m->SharedClipboard.mapClipboardAreas.end())
+        {
+            uint32_t cRefs = itArea->second.Area.AddRef();
+            LogFlowThisFunc(("aID=%RU32 -> cRefs=%RU32\n", aID, cRefs));
+            rc = VINF_SUCCESS;
+        }
+        else
+            rc = VERR_NOT_FOUND;
+
+        int rc2 = RTCritSectLeave(&m->SharedClipboard.CritSect);
+        AssertRC(rc2);
+    }
+    LogFlowThisFunc(("aID=%RU32, rc=%Rrc\n", aID, rc));
+    return rc;
+}
+
+int VirtualBox::i_onClipboardAreaDetach(ULONG aID)
+{
+    int rc = RTCritSectEnter(&m->SharedClipboard.CritSect);
+    if (RT_SUCCESS(rc))
+    {
+        SharedClipboardAreaMap::iterator itArea = m->SharedClipboard.mapClipboardAreas.find(aID);
+        if (itArea != m->SharedClipboard.mapClipboardAreas.end())
+        {
+            uint32_t cRefs = itArea->second.Area.Release();
+            LogFlowThisFunc(("aID=%RU32 -> cRefs=%RU32\n", aID, cRefs));
+            rc = VINF_SUCCESS;
+        }
+        else
+            rc = VERR_NOT_FOUND;
+
+        int rc2 = RTCritSectLeave(&m->SharedClipboard.CritSect);
+        AssertRC(rc2);
+    }
+    LogFlowThisFunc(("aID=%RU32, rc=%Rrc\n", aID, rc));
+    return rc;
+}
+
+ULONG VirtualBox::i_onClipboardAreaGetMostRecent(void)
+{
+    ULONG aID = 0;
+    int rc2 = RTCritSectEnter(&m->SharedClipboard.CritSect);
+    if (RT_SUCCESS(rc2))
+    {
+        aID = m->SharedClipboard.uNextClipboardAreaID
+            ? m->SharedClipboard.uNextClipboardAreaID - 1 : 0;
+
+        rc2 = RTCritSectLeave(&m->SharedClipboard.CritSect);
+        AssertRC(rc2);
+    }
+    LogFlowThisFunc(("aID=%RU32\n", aID));
+    return aID;
+}
+
+ULONG VirtualBox::i_onClipboardAreaGetRefCount(ULONG aID)
+{
+    ULONG cRefCount = 0;
+    int rc2 = RTCritSectEnter(&m->SharedClipboard.CritSect);
+    if (RT_SUCCESS(rc2))
+    {
+        SharedClipboardAreaMap::iterator itArea = m->SharedClipboard.mapClipboardAreas.find(aID);
+        if (itArea != m->SharedClipboard.mapClipboardAreas.end())
+        {
+            cRefCount = itArea->second.Area.GetRefCount();
+        }
+
+        rc2 = RTCritSectLeave(&m->SharedClipboard.CritSect);
+        AssertRC(rc2);
+    }
+    LogFlowThisFunc(("aID=%RU32, cRefCount=%RU32\n", aID, cRefCount));
+    return cRefCount;
+}
+#endif /* VBOX_WITH_SHARED_CLIPBOARD_URI_LIST */
+
 /**
  *  @note Doesn't lock any object.
