Index: /trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxClipboard.cpp
===================================================================
--- /trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxClipboard.cpp	(revision 58603)
+++ /trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxClipboard.cpp	(revision 58604)
@@ -20,4 +20,5 @@
 
 #include <iprt/asm.h>
+#include <iprt/ldr.h>
 
 #include <VBox/HostServices/VBoxClipboardSvc.h>
@@ -31,5 +32,14 @@
 #include <VBox/log.h>
 
-
+ /* Dynamically load clipboard functions from User32.dll. */
+typedef BOOL WINAPI FNADDCLIPBOARDFORMATLISTENER(HWND);
+typedef FNADDCLIPBOARDFORMATLISTENER *PFNADDCLIPBOARDFORMATLISTENER;
+
+typedef BOOL WINAPI FNREMOVECLIPBOARDFORMATLISTENER(HWND);
+typedef FNREMOVECLIPBOARDFORMATLISTENER *PFNREMOVECLIPBOARDFORMATLISTENER;
+
+#ifndef WM_CLIPBOARDUPDATE
+#define WM_CLIPBOARDUPDATE 0x031D
+#endif
 
 typedef struct _VBOXCLIPBOARDCONTEXT
@@ -42,4 +52,6 @@
     UINT                  timerRefresh;
     bool                  fCBChainPingInProcess;
+    PFNADDCLIPBOARDFORMATLISTENER pfnAddClipboardFormatListener;
+    PFNREMOVECLIPBOARDFORMATLISTENER pfnRemoveClipboardFormatListener;
 } VBOXCLIPBOARDCONTEXT, *PVBOXCLIPBOARDCONTEXT;
 
@@ -50,4 +62,36 @@
 
 enum { CBCHAIN_TIMEOUT = 5000 /* ms */ };
+
+static void vboxClipboardInitNewAPI(VBOXCLIPBOARDCONTEXT *pCtx)
+{
+    RTLDRMOD hUser32 = NIL_RTLDRMOD;
+    int rc = RTLdrLoadSystem("User32.dll", /* fNoUnload = */ true, &hUser32);
+    if (RT_SUCCESS(rc))
+    {
+        rc = RTLdrGetSymbol(hUser32, "AddClipboardFormatListener", (void**)&pCtx->pfnAddClipboardFormatListener);
+        if (RT_SUCCESS(rc))
+        {
+            rc = RTLdrGetSymbol(hUser32, "RemoveClipboardFormatListener", (void**)&pCtx->pfnRemoveClipboardFormatListener);
+        }
+
+        RTLdrClose(hUser32);
+    }
+
+    if (RT_SUCCESS(rc))
+    {
+        Log(("New Clipboard API is enabled\n"));
+    }
+    else
+    {
+        pCtx->pfnAddClipboardFormatListener = NULL;
+        pCtx->pfnRemoveClipboardFormatListener = NULL;
+        Log(("New Clipboard API is not available. rc = %Rrc\n", rc));
+    }
+}
+
+static bool vboxClipboardIsNewAPI(VBOXCLIPBOARDCONTEXT *pCtx)
+{
+    return pCtx->pfnAddClipboardFormatListener != NULL;
+}
 
 static int vboxClipboardChanged(PVBOXCLIPBOARDCONTEXT pCtx)
@@ -111,5 +155,8 @@
 {
     AssertPtrReturnVoid(pCtx);
-    pCtx->hwndNextInChain = SetClipboardViewer(pCtx->hwnd);
+    if (vboxClipboardIsNewAPI(pCtx))
+        pCtx->pfnAddClipboardFormatListener(pCtx->hwnd);
+    else
+        pCtx->hwndNextInChain = SetClipboardViewer(pCtx->hwnd);
     /** @todo r=andy Return code?? */
 }
@@ -120,6 +167,13 @@
     AssertPtrReturnVoid(pCtx);
 
-    ChangeClipboardChain(pCtx->hwnd, pCtx->hwndNextInChain);
-    pCtx->hwndNextInChain = NULL;
+    if (vboxClipboardIsNewAPI(pCtx))
+    {
+        pCtx->pfnRemoveClipboardFormatListener(pCtx->hwnd);
+    }
+    else
+    {
+        ChangeClipboardChain(pCtx->hwnd, pCtx->hwndNextInChain);
+        pCtx->hwndNextInChain = NULL;
+    }
     /** @todo r=andy Return code?? */
 }
@@ -150,6 +204,23 @@
     switch (msg)
     {
+        case WM_CLIPBOARDUPDATE:
+        {
+            Log(("WM_CLIPBOARDUPDATE\n"));
+
+            if (GetClipboardOwner() != hwnd)
+            {
+                /* Clipboard was updated by another application. */
+                vboxClipboardChanged(pCtx);
+            }
+        } break;
+
         case WM_CHANGECBCHAIN:
         {
+            if (vboxClipboardIsNewAPI(pCtx))
+            {
+                rc = DefWindowProc(hwnd, msg, wParam, lParam);
+                break;
+            }
+
             HWND hwndRemoved = (HWND)wParam;
             HWND hwndNext    = (HWND)lParam;
@@ -180,5 +251,5 @@
             LogFlowFunc(("WM_DRAWCLIPBOARD, hwnd %p\n", pCtx->hwnd));
 
-            if (GetClipboardOwner () != hwnd)
+            if (GetClipboardOwner() != hwnd)
             {
                 /* Clipboard was updated by another application. */
@@ -189,10 +260,16 @@
             }
 
-            /* Pass the message to next windows in the clipboard chain. */
-            SendMessageTimeout(pCtx->hwndNextInChain, msg, wParam, lParam, 0, CBCHAIN_TIMEOUT, NULL);
+            if (pCtx->hwndNextInChain)
+            {
+                /* Pass the message to next windows in the clipboard chain. */
+                SendMessageTimeout(pCtx->hwndNextInChain, msg, wParam, lParam, 0, CBCHAIN_TIMEOUT, NULL);
+            }
         } break;
 
         case WM_TIMER:
         {
+            if (vboxClipboardIsNewAPI(pCtx))
+                break;
+
             HWND hViewer = GetClipboardViewer();
 
@@ -209,5 +286,5 @@
             hViewer = GetClipboardViewer();
             if (hViewer)
-                SendMessageCallback(hViewer, WM_CHANGECBCHAIN, (WPARAM)pCtx->hwndNextInChain, (LPARAM)pCtx->hwndNextInChain, vboxClipboardChainPingProc, (ULONG_PTR) pCtx);
+                SendMessageCallback(hViewer, WM_CHANGECBCHAIN, (WPARAM)pCtx->hwndNextInChain, (LPARAM)pCtx->hwndNextInChain, vboxClipboardChainPingProc, (ULONG_PTR)pCtx);
         } break;
 
@@ -591,5 +668,6 @@
 
             vboxClipboardAddToCBChain(pCtx);
-            pCtx->timerRefresh = SetTimer(pCtx->hwnd, 0, 10 * 1000, NULL);
+            if (!vboxClipboardIsNewAPI(pCtx))
+                pCtx->timerRefresh = SetTimer(pCtx->hwnd, 0, 10 * 1000, NULL);
         }
     }
@@ -651,4 +729,7 @@
     RT_BZERO(pCtx, sizeof(VBOXCLIPBOARDCONTEXT));
     pCtx->pEnv = pEnv;
+
+    /* Check that new Clipboard API is available */
+    vboxClipboardInitNewAPI(pCtx);
 
     int rc = VbglR3ClipboardConnect(&pCtx->u32ClientID);
@@ -798,3 +879,2 @@
     VBoxClipboardDestroy
 };
-
Index: /trunk/src/VBox/HostServices/SharedClipboard/VBoxClipboard-win.cpp
===================================================================
--- /trunk/src/VBox/HostServices/SharedClipboard/VBoxClipboard-win.cpp	(revision 58603)
+++ /trunk/src/VBox/HostServices/SharedClipboard/VBoxClipboard-win.cpp	(revision 58604)
@@ -4,5 +4,5 @@
 
 /*
- * Copyright (C) 2006-2011 Oracle Corporation
+ * Copyright (C) 2006-2015 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
@@ -24,4 +24,5 @@
 #include <iprt/assert.h>
 #include <iprt/thread.h>
+#include <iprt/ldr.h>
 #include <process.h>
 
@@ -33,4 +34,15 @@
 
 enum { CBCHAIN_TIMEOUT = 5000 /* ms */ };
+
+/* Dynamically load clipboard functions from User32.dll. */
+typedef BOOL WINAPI FNADDCLIPBOARDFORMATLISTENER(HWND);
+typedef FNADDCLIPBOARDFORMATLISTENER *PFNADDCLIPBOARDFORMATLISTENER;
+
+typedef BOOL WINAPI FNREMOVECLIPBOARDFORMATLISTENER(HWND);
+typedef FNREMOVECLIPBOARDFORMATLISTENER *PFNREMOVECLIPBOARDFORMATLISTENER;
+
+#ifndef WM_CLIPBOARDUPDATE
+#define WM_CLIPBOARDUPDATE 0x031D
+#endif
 
 struct _VBOXCLIPBOARDCONTEXT
@@ -49,4 +61,8 @@
 
     VBOXCLIPBOARDCLIENTDATA *pClient;
+
+    PFNADDCLIPBOARDFORMATLISTENER    pfnAddClipboardFormatListener;
+    PFNREMOVECLIPBOARDFORMATLISTENER pfnRemoveClipboardFormatListener;
+
 };
 
@@ -95,4 +111,36 @@
 #endif /* LOG_ENABLED */
 
+static void vboxClipboardInitNewAPI(VBOXCLIPBOARDCONTEXT *pCtx)
+{
+    RTLDRMOD hUser32 = NIL_RTLDRMOD;
+    int rc = RTLdrLoadSystem("User32.dll", /* fNoUnload = */ true, &hUser32);
+    if (RT_SUCCESS(rc))
+    {
+        rc = RTLdrGetSymbol(hUser32, "AddClipboardFormatListener", (void**)&pCtx->pfnAddClipboardFormatListener);
+        if (RT_SUCCESS(rc))
+        {
+            rc = RTLdrGetSymbol(hUser32, "RemoveClipboardFormatListener", (void**)&pCtx->pfnRemoveClipboardFormatListener);
+        }
+
+        RTLdrClose(hUser32);
+    }
+
+    if (RT_SUCCESS(rc))
+    {
+        Log(("New Clipboard API is enabled\n"));
+    }
+    else
+    {
+        pCtx->pfnAddClipboardFormatListener = NULL;
+        pCtx->pfnRemoveClipboardFormatListener = NULL;
+        Log(("New Clipboard API is not available. rc = %Rrc\n", rc));
+    }
+}
+
+static bool vboxClipboardIsNewAPI(VBOXCLIPBOARDCONTEXT *pCtx)
+{
+    return pCtx->pfnAddClipboardFormatListener != NULL;
+}
+
 static void vboxClipboardGetData (uint32_t u32Format, const void *pvSrc, uint32_t cbSrc,
                                   void *pvDst, uint32_t cbDst, uint32_t *pcbActualDst)
@@ -120,4 +168,5 @@
 {
     Assert(pCtx->pClient);
+    Assert(pCtx->hRenderEvent);
     Assert(pCtx->pClient->data.pv == NULL && pCtx->pClient->data.cb == 0 && pCtx->pClient->data.u32Format == 0);
 
@@ -128,7 +177,7 @@
     vboxSvcClipboardReportMsg (pCtx->pClient, VBOX_SHARED_CLIPBOARD_HOST_MSG_READ_DATA, u32Format);
 
-    WaitForSingleObject(pCtx->hRenderEvent, INFINITE);
-
-    LogFlow(("vboxClipboardReadDataFromClient wait completed\n"));
+    DWORD ret = WaitForSingleObject(pCtx->hRenderEvent, INFINITE);
+    LogFlow(("vboxClipboardReadDataFromClient wait completed, ret 0x%08X, err %d\n",
+             ret, GetLastError())); NOREF(ret);
 
     return VINF_SUCCESS;
@@ -196,5 +245,8 @@
 static void addToCBChain (VBOXCLIPBOARDCONTEXT *pCtx)
 {
-    pCtx->hwndNextInChain = SetClipboardViewer (pCtx->hwnd);
+    if (vboxClipboardIsNewAPI(pCtx))
+        pCtx->pfnAddClipboardFormatListener(pCtx->hwnd);
+    else
+        pCtx->hwndNextInChain = SetClipboardViewer(pCtx->hwnd);
 }
 
@@ -202,6 +254,13 @@
 static void removeFromCBChain (VBOXCLIPBOARDCONTEXT *pCtx)
 {
-    ChangeClipboardChain (pCtx->hwnd, pCtx->hwndNextInChain);
-    pCtx->hwndNextInChain = NULL;
+    if (vboxClipboardIsNewAPI(pCtx))
+    {
+        pCtx->pfnRemoveClipboardFormatListener(pCtx->hwnd);
+    }
+    else
+    {
+        ChangeClipboardChain(pCtx->hwnd, pCtx->hwndNextInChain);
+        pCtx->hwndNextInChain = NULL;
+    }
 }
 
@@ -227,7 +286,24 @@
     switch (msg)
     {
+        case WM_CLIPBOARDUPDATE:
+        {
+            Log(("WM_CLIPBOARDUPDATE\n"));
+
+            if (GetClipboardOwner() != hwnd)
+            {
+                /* Clipboard was updated by another application. */
+                vboxClipboardChanged(pCtx);
+            }
+        } break;
+
         case WM_CHANGECBCHAIN:
         {
             Log(("WM_CHANGECBCHAIN\n"));
+
+            if (vboxClipboardIsNewAPI(pCtx))
+            {
+                rc = DefWindowProc(hwnd, msg, wParam, lParam);
+                break;
+            }
 
             HWND hwndRemoved = (HWND)wParam;
@@ -256,5 +332,5 @@
         case WM_DRAWCLIPBOARD:
         {
-            Log(("WM_DRAWCLIPBOARD next %p\n", pCtx->hwndNextInChain));
+            Log(("WM_DRAWCLIPBOARD\n"));
 
             if (GetClipboardOwner () != hwnd)
@@ -266,4 +342,5 @@
             if (pCtx->hwndNextInChain)
             {
+                Log(("WM_DRAWCLIPBOARD next %p\n", pCtx->hwndNextInChain));
                 /* Pass the message to next windows in the clipboard chain. */
                 DWORD_PTR dwResult;
@@ -276,4 +353,7 @@
         case WM_TIMER:
         {
+            if (vboxClipboardIsNewAPI(pCtx))
+                break;
+
             HWND hViewer = GetClipboardViewer();
 
@@ -292,10 +372,5 @@
                 SendMessageCallback(hViewer, WM_CHANGECBCHAIN, (WPARAM)pCtx->hwndNextInChain, (LPARAM)pCtx->hwndNextInChain, CBChainPingProc, (ULONG_PTR) pCtx);
         } break;
-
-        case WM_CLOSE:
-        {
-            /* Do nothing. Ignore the message. */
-        } break;
-
+		        
         case WM_RENDERFORMAT:
         {
@@ -344,6 +419,7 @@
             {
                 int vboxrc = vboxClipboardReadDataFromClient (pCtx, u32Format);
-
-                dprintf(("vboxClipboardReadDataFromClient vboxrc = %d\n", vboxrc));
+                
+                dprintf(("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)
@@ -430,4 +506,5 @@
                  * because host clipboard has more priority.
                  */
+                Log(("WM_USER ignored\n"));
                 break;
             }
@@ -480,8 +557,13 @@
         } break;
 
+        case WM_CLOSE:
+        {
+            /* Do nothing. Ignore the message. */
+        } break;
+
         default:
         {
             Log(("WM_ %p\n", msg));
-            rc = DefWindowProc (hwnd, msg, wParam, lParam);
+            rc = DefWindowProc(hwnd, msg, wParam, lParam);
         }
     }
@@ -500,21 +582,17 @@
     VBOXCLIPBOARDCONTEXT *pCtx = &g_ctx;
 
-    HINSTANCE hInstance = (HINSTANCE)GetModuleHandle (NULL);
+    HINSTANCE hInstance = (HINSTANCE)GetModuleHandle(NULL);
 
     /* Register the Window Class. */
     WNDCLASS wc;
+    RT_ZERO(wc);
 
     wc.style         = CS_NOCLOSE;
     wc.lpfnWndProc   = vboxClipboardWndProc;
-    wc.cbClsExtra    = 0;
-    wc.cbWndExtra    = 0;
     wc.hInstance     = hInstance;
-    wc.hIcon         = NULL;
-    wc.hCursor       = NULL;
     wc.hbrBackground = (HBRUSH)(COLOR_BACKGROUND + 1);
-    wc.lpszMenuName  = NULL;
     wc.lpszClassName = gachWindowClassName;
 
-    ATOM atomWindowClass = RegisterClass (&wc);
+    ATOM atomWindowClass = RegisterClass(&wc);
 
     if (atomWindowClass == 0)
@@ -542,5 +620,6 @@
 
             addToCBChain(pCtx);
-            pCtx->timerRefresh = SetTimer(pCtx->hwnd, 0, 10 * 1000, NULL);
+            if (!vboxClipboardIsNewAPI(pCtx))
+                pCtx->timerRefresh = SetTimer(pCtx->hwnd, 0, 10 * 1000, NULL);
 
             MSG msg;
@@ -578,4 +657,9 @@
 {
     int rc = VINF_SUCCESS;
+
+    RT_ZERO(g_ctx);
+
+    /* Check that new Clipboard API is available */
+    vboxClipboardInitNewAPI(&g_ctx);
 
     g_ctx.hRenderEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
