Author: hbelusca
Date: Sun Feb 14 18:41:49 2016
New Revision: 70744

URL: http://svn.reactos.org/svn/reactos?rev=70744&view=rev
Log:
[WIN32K:NTUSER]
- Cleanup window clipboard data while the window still exists and is not 
dereferenced.
- When a window is about to be destroyed (just before we send the WM_DESTROY 
message), if it is the current clipboard owner, make it release the clipboard. 
The WM_RENDERALLFORMATS message is then sent, and if needed, one 
WM_DRAWCLIPBOARD message.
- Send a WM_DRAWCLIPBOARD message when SetClipboardViewer is called.
WM_DRAWCLIPBOARD messages are sent as notifications to the corresponding 
windows.

Modified:
    trunk/reactos/win32ss/user/ntuser/clipboard.c
    trunk/reactos/win32ss/user/ntuser/clipboard.h
    trunk/reactos/win32ss/user/ntuser/window.c

Modified: trunk/reactos/win32ss/user/ntuser/clipboard.c
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/user/ntuser/clipboard.c?rev=70744&r1=70743&r2=70744&view=diff
==============================================================================
--- trunk/reactos/win32ss/user/ntuser/clipboard.c       [iso-8859-1] (original)
+++ trunk/reactos/win32ss/user/ntuser/clipboard.c       [iso-8859-1] Sun Feb 14 
18:41:49 2016
@@ -346,6 +346,43 @@
     pWinSta->cNumClipFormats = 0;
 }
 
+/* UserClipboardRelease is called from IntSendDestroyMsg in window.c */
+VOID FASTCALL
+UserClipboardRelease(PWND pWindow)
+{
+    PWINSTATION_OBJECT pWinStaObj;
+
+    pWinStaObj = IntGetWinStaForCbAccess();
+    if (!pWinStaObj)
+        return;
+
+    co_IntSendMessage(pWinStaObj->spwndClipOwner->head.h, WM_RENDERALLFORMATS, 
0, 0);
+
+    /* If the window being destroyed is the current clipboard owner... */
+    if (pWindow == pWinStaObj->spwndClipOwner)
+    {
+        /* ... make it release the clipboard */
+        pWinStaObj->spwndClipOwner = NULL;
+    }
+
+    if (pWinStaObj->fClipboardChanged)
+    {
+        /* Add synthesized formats - they are rendered later */
+        IntAddSynthesizedFormats(pWinStaObj);
+
+        /* Notify viewer windows in chain */
+        pWinStaObj->fClipboardChanged = FALSE;
+        if (pWinStaObj->spwndClipViewer)
+        {
+            TRACE("Clipboard: sending WM_DRAWCLIPBOARD to %p\n", 
pWinStaObj->spwndClipViewer->head.h);
+            // For 32-bit applications this message is sent as a notification
+            co_IntSendMessageNoWait(pWinStaObj->spwndClipViewer->head.h, 
WM_DRAWCLIPBOARD, 0, 0);
+        }
+    }
+
+    ObDereferenceObject(pWinStaObj);
+}
+
 /* UserClipboardFreeWindow is called from co_UserFreeWindow in window.c */
 VOID FASTCALL
 UserClipboardFreeWindow(PWND pWindow)
@@ -356,17 +393,18 @@
     if (!pWinStaObj)
         return;
 
+    if (pWindow == pWinStaObj->spwndClipOwner)
+    {
+        /* The owner window was destroyed */
+        pWinStaObj->spwndClipOwner = NULL;
+    }
+
     /* Check if clipboard is not locked by this window, if yes, unlock it */
     if (pWindow == pWinStaObj->spwndClipOpen)
     {
         /* The window that opens the clipboard was destroyed */
         pWinStaObj->spwndClipOpen = NULL;
         pWinStaObj->ptiClipLock = NULL;
-    }
-    if (pWindow == pWinStaObj->spwndClipOwner)
-    {
-        /* The owner window was destroyed */
-        pWinStaObj->spwndClipOwner = NULL;
     }
     /* Remove window from window chain */
     if (pWindow == pWinStaObj->spwndClipViewer)
@@ -500,13 +538,13 @@
         IntAddSynthesizedFormats(pWinStaObj);
 
         /* Notify viewer windows in chain */
+        pWinStaObj->fClipboardChanged = FALSE;
         if (pWinStaObj->spwndClipViewer)
         {
             TRACE("Clipboard: sending WM_DRAWCLIPBOARD to %p\n", 
pWinStaObj->spwndClipViewer->head.h);
-            co_IntSendMessage(pWinStaObj->spwndClipViewer->head.h, 
WM_DRAWCLIPBOARD, 0, 0);
+            // For 32-bit applications this message is sent as a notification
+            co_IntSendMessageNoWait(pWinStaObj->spwndClipViewer->head.h, 
WM_DRAWCLIPBOARD, 0, 0);
         }
-
-        pWinStaObj->fClipboardChanged = FALSE;
     }
 
 cleanup:
@@ -629,6 +667,7 @@
     if (pWinStaObj->spwndClipOwner)
     {
         TRACE("Clipboard: WM_DESTROYCLIPBOARD to %p\n", 
pWinStaObj->spwndClipOwner->head.h);
+        // For 32-bit applications this message is sent as a notification
         co_IntSendMessageNoWait(pWinStaObj->spwndClipOwner->head.h, 
WM_DESTROYCLIPBOARD, 0, 0);
     }
 
@@ -1053,6 +1092,15 @@
     /* Set new viewer window */
     pWinStaObj->spwndClipViewer = pWindow;
 
+    /* Notify viewer windows in chain */
+    pWinStaObj->fClipboardChanged = FALSE;
+    if (pWinStaObj->spwndClipViewer)
+    {
+        TRACE("Clipboard: sending WM_DRAWCLIPBOARD to %p\n", 
pWinStaObj->spwndClipViewer->head.h);
+        // For 32-bit applications this message is sent as a notification
+        co_IntSendMessageNoWait(pWinStaObj->spwndClipViewer->head.h, 
WM_DRAWCLIPBOARD, 0, 0);
+    }
+
 cleanup:
     if (pWinStaObj)
         ObDereferenceObject(pWinStaObj);

Modified: trunk/reactos/win32ss/user/ntuser/clipboard.h
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/user/ntuser/clipboard.h?rev=70744&r1=70743&r2=70744&view=diff
==============================================================================
--- trunk/reactos/win32ss/user/ntuser/clipboard.h       [iso-8859-1] (original)
+++ trunk/reactos/win32ss/user/ntuser/clipboard.h       [iso-8859-1] Sun Feb 14 
18:41:49 2016
@@ -9,6 +9,9 @@
 
 UINT APIENTRY
 UserEnumClipboardFormats(UINT uFormat);
+
+VOID FASTCALL
+UserClipboardRelease(PWND pWindow);
 
 VOID FASTCALL
 UserClipboardFreeWindow(PWND pWindow);

Modified: trunk/reactos/win32ss/user/ntuser/window.c
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/user/ntuser/window.c?rev=70744&r1=70743&r2=70744&view=diff
==============================================================================
--- trunk/reactos/win32ss/user/ntuser/window.c  [iso-8859-1] (original)
+++ trunk/reactos/win32ss/user/ntuser/window.c  [iso-8859-1] Sun Feb 14 
18:41:49 2016
@@ -424,10 +424,14 @@
       }
    }
 
-   /*
-    * Send the WM_DESTROY to the window.
-    */
-
+   /* If the window being destroyed is the current clipboard owner... */
+   if (ti->ppi->prpwinsta != NULL && Window == 
ti->ppi->prpwinsta->spwndClipOwner)
+   {
+       /* ... make it release the clipboard */
+       UserClipboardRelease(Window);
+   }
+
+   /* Send the WM_DESTROY to the window */
    co_IntSendMessage(hWnd, WM_DESTROY, 0, 0);
 
    /*
@@ -554,6 +558,8 @@
          co_IntSendMessage(UserHMGetHandle(Window), WM_NCDESTROY, 0, 0);
    }
 
+   UserClipboardFreeWindow(Window);
+
    DestroyTimersForWindow(ThreadData, Window);
 
    /* Unregister hot keys */
@@ -664,8 +670,6 @@
    UserFreeWindowInfo(Window->head.pti, Window);
 
    UserDereferenceObject(Window);
-
-   UserClipboardFreeWindow(Window);
 
    return 0;
 }


Reply via email to