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/clipboa... ============================================================================== --- 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/clipboa... ============================================================================== --- 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.... ============================================================================== --- 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; }