Allow applications, under certain conditions, to set data into the
clipboard even if they are not the clipboard owners.

diff --git a/dlls/x11drv/clipboard.c b/dlls/x11drv/clipboard.c
index e8afaf2..5dbb9e1 100644
--- a/dlls/x11drv/clipboard.c
+++ b/dlls/x11drv/clipboard.c
@@ -117,7 +117,7 @@
 static Window ClipboardSelectionOwner = None;  /* The window which owns the clipboard selection */
 
 INT X11DRV_RegisterClipboardFormat(LPCSTR FormatName);
-void X11DRV_EmptyClipboard(void);
+void X11DRV_EmptyClipboard(BOOL keepunowned);
 void X11DRV_EndClipboardUpdate(void);
 HANDLE X11DRV_CLIPBOARD_ImportClipboardData(LPBYTE lpdata, UINT cBytes);
 HANDLE X11DRV_CLIPBOARD_ImportEnhMetaFile(LPBYTE lpdata, UINT cBytes);
@@ -719,7 +719,7 @@
         }
         else if (wSeqNo < lpcbinfo->seqno)
         {
-            X11DRV_EmptyClipboard();
+            X11DRV_EmptyClipboard(TRUE);
 
             if (X11DRV_CLIPBOARD_QueryAvailableData(lpcbinfo) < 0)
             {
@@ -1985,7 +1985,7 @@
                 selectionWindow = None;
                 PrimarySelectionOwner = ClipboardSelectionOwner = 0;
 
-                X11DRV_EmptyClipboard();
+                X11DRV_EmptyClipboard(FALSE);
 
                 /* Reset the selection flags now that we are done */
                 selectionAcquired = S_NOSELECTION;
@@ -2135,29 +2135,41 @@
 
 /**************************************************************************
  *	X11DRV_EmptyClipboard
+ *
+ * Empty cached clipboard data. 
  */
-void X11DRV_EmptyClipboard(void)
+void X11DRV_EmptyClipboard(BOOL keepunowned)
 {
     if (ClipData)
     {
-        LPWINE_CLIPDATA lpData;
+        LPWINE_CLIPDATA lpData, lpStart;
         LPWINE_CLIPDATA lpNext = ClipData;
 
+        TRACE(" called with %d entries in cache.\n", ClipDataCount);
+
         do
         {
+            lpStart = ClipData;
             lpData = lpNext;
             lpNext = lpData->NextData;
+
+            if (!keepunowned || !(lpData->wFlags & CF_FLAG_UNOWNED))
+            {
             lpData->PrevData->NextData = lpData->NextData;
             lpData->NextData->PrevData = lpData->PrevData;
+
+                if (lpData == ClipData)
+                    ClipData = lpNext != lpData ? lpNext : NULL;
+
             X11DRV_CLIPBOARD_FreeData(lpData);
             HeapFree(GetProcessHeap(), 0, lpData);
-        } while (lpNext != lpData);
+
+                ClipDataCount--;
+            }
+        } while (lpNext != lpStart);
     }
 
-    TRACE(" %d entries deleted from cache.\n", ClipDataCount);
-
-    ClipData = NULL;
-    ClipDataCount = 0;
+    TRACE(" %d entries remaining in cache.\n", ClipDataCount);
 }
 
 
@@ -2165,12 +2177,29 @@
 /**************************************************************************
  *		X11DRV_SetClipboardData
  */
-BOOL X11DRV_SetClipboardData(UINT wFormat, HANDLE16 hData16, HANDLE hData32)
+BOOL X11DRV_SetClipboardData(UINT wFormat, HANDLE16 hData16, HANDLE hData32, BOOL owner)
 {
-    BOOL bResult = FALSE;
+    DWORD flags = 0;
+    BOOL bResult = TRUE;
 
-    if (X11DRV_CLIPBOARD_InsertClipboardData(wFormat, hData16, hData32, 0))
-        bResult = TRUE;
+    /* If it's not owned, data can only be set if the format data is not already owned
+       and its rendering is not delayed */
+    if (!owner)
+{
+        CLIPBOARDINFO cbinfo;
+        LPWINE_CLIPDATA lpRender;
+
+        X11DRV_CLIPBOARD_UpdateCache(&cbinfo);
+
+        if ((!hData16 && !hData32) ||
+            ((lpRender = X11DRV_CLIPBOARD_LookupData(wFormat)) &&
+            !(lpRender->wFlags & CF_FLAG_UNOWNED)))
+            bResult = FALSE;
+        else
+            flags = CF_FLAG_UNOWNED;
+    }
+
+    bResult &= X11DRV_CLIPBOARD_InsertClipboardData(wFormat, hData16, hData32, flags);
 
     return bResult;
 }
diff --git a/dlls/x11drv/x11drv.h b/dlls/x11drv/x11drv.h
index fcc26c3..098c8c6 100644
--- a/dlls/x11drv/x11drv.h
+++ b/dlls/x11drv/x11drv.h
@@ -474,6 +474,7 @@
 } WINE_CLIPFORMAT, *LPWINE_CLIPFORMAT;
 
 #define CF_FLAG_BUILTINFMT   1 /* Built-in windows format */
+#define CF_FLAG_UNOWNED      2 /* cached data is not owned */
 #define CF_FLAG_SYNTHESIZED  8 /* Implicitly converted data */
 
 extern void X11DRV_InitClipboard(void);
diff --git a/include/user.h b/include/user.h
index cf48024..5f2a420 100644
--- a/include/user.h
+++ b/include/user.h
@@ -94,7 +94,7 @@
     /* clipboard functions */
     void   (*pAcquireClipboard)(HWND);                     /* Acquire selection */
     BOOL   (*pCountClipboardFormats)(void);                /* Count available clipboard formats */
-    void   (*pEmptyClipboard)(void);                       /* Empty clipboard data */
+    void   (*pEmptyClipboard)(BOOL);                       /* Empty clipboard data */
     BOOL   (*pEndClipboardUpdate)(void);                   /* End clipboard update */
     BOOL   (*pEnumClipboardFormats)(UINT);                 /* Enumerate clipboard formats */
     BOOL   (*pGetClipboardData)(UINT, HANDLE16*, HANDLE*); /* Get specified selection data */
@@ -102,7 +102,7 @@
     BOOL   (*pIsClipboardFormatAvailable)(UINT);           /* Check if specified format is available */
     INT    (*pRegisterClipboardFormat)(LPCSTR);            /* Register a clipboard format */
     void   (*pResetSelectionOwner)(HWND, BOOL);
-    BOOL   (*pSetClipboardData)(UINT, HANDLE16, HANDLE);   /* Set specified selection data */
+    BOOL   (*pSetClipboardData)(UINT, HANDLE16, HANDLE, BOOL);   /* Set specified selection data */
     /* display modes */
     LONG   (*pChangeDisplaySettingsExW)(LPCWSTR,LPDEVMODEW,HWND,DWORD,LPVOID);
     BOOL   (*pEnumDisplaySettingsExW)(LPCWSTR,DWORD,LPDEVMODEW,DWORD);
diff --git a/windows/clipboard.c b/windows/clipboard.c
index fda151e..85117cf 100644
--- a/windows/clipboard.c
+++ b/windows/clipboard.c
@@ -427,7 +427,7 @@
 
     /* Empty the local cache */
     if (USER_Driver.pEmptyClipboard) 
-        USER_Driver.pEmptyClipboard();
+        USER_Driver.pEmptyClipboard(FALSE);
  
     bCBHasChanged = TRUE;
 
@@ -557,14 +557,22 @@
 
     TRACE("(%04X, %04x) !\n", wFormat, hData);
 
-    if (!CLIPBOARD_GetClipboardInfo(&cbinfo) ||
-        (~cbinfo.flags & CB_OPEN) ||
-        (~cbinfo.flags & CB_OWNER))
+    if (!CLIPBOARD_GetClipboardInfo(&cbinfo) || !(cbinfo.flags & CB_OPEN))
     {
-        WARN("Clipboard not opened by calling task!\n");
+        WARN("Clipboard not opened by calling task. Operation failed.\n");
+        return 0;
     }
-    else if (USER_Driver.pSetClipboardData &&
-        USER_Driver.pSetClipboardData(wFormat, hData, 0))
+
+    /* If it's not owned, data can only be set if the format doesn't exists
+       and its rendering is not delayed */
+    if (!(cbinfo.flags & CB_OWNER) && !hData)
+    {
+        WARN("Clipboard not owned by calling task. Operation failed.\n");
+        return 0;
+    }
+
+    if (USER_Driver.pSetClipboardData &&
+        USER_Driver.pSetClipboardData(wFormat, hData, 0, cbinfo.flags & CB_OWNER))
     {
         hResult = hData;
         bCBHasChanged = TRUE;
@@ -584,13 +592,22 @@
 
     TRACE("(%04X, %p) !\n", wFormat, hData);
 
-    if (!CLIPBOARD_GetClipboardInfo(&cbinfo) ||
-        (~cbinfo.flags & CB_OWNER))
+    if (!CLIPBOARD_GetClipboardInfo(&cbinfo) || !(cbinfo.flags & CB_OPEN))
     {
-        WARN("Clipboard not owned by calling task!\n");
+        WARN("Clipboard not opened by calling task. Operation failed.\n");
+        return 0;
     }
-    else if (USER_Driver.pSetClipboardData &&
-        USER_Driver.pSetClipboardData(wFormat, 0, hData))
+
+    /* If it's not owned, data can only be set if the format isn't
+       available and its rendering is not delayed */
+    if (!(cbinfo.flags & CB_OWNER) && !hData)
+    {
+        WARN("Clipboard not owned by calling task. Operation failed.\n");
+        return 0;
+    }
+
+    if (USER_Driver.pSetClipboardData &&
+        USER_Driver.pSetClipboardData(wFormat, 0, hData, cbinfo.flags & CB_OWNER))
     {
         hResult = hData;
         bCBHasChanged = TRUE;