Fix race condition when one thread changes the update region of a window

and another thread retrieves a paint message for that window.

svn path=/trunk/; revision=8033
This commit is contained in:
Gé van Geldorp 2004-02-04 23:01:07 +00:00
parent 969bf0b926
commit 8fdb9cdcc1
3 changed files with 25 additions and 6 deletions

View file

@ -59,6 +59,8 @@ typedef struct _WINDOW_OBJECT
/* Handle of region of the window to be updated. */ /* Handle of region of the window to be updated. */
HANDLE UpdateRegion; HANDLE UpdateRegion;
HANDLE NCUpdateRegion; HANDLE NCUpdateRegion;
/* Lock to be held when manipulating (NC)UpdateRegion */
FAST_MUTEX UpdateLock;
/* Pointer to the owning thread's message queue. */ /* Pointer to the owning thread's message queue. */
PUSER_MESSAGE_QUEUE MessageQueue; PUSER_MESSAGE_QUEUE MessageQueue;
struct _WINDOW_OBJECT* FirstChild; struct _WINDOW_OBJECT* FirstChild;

View file

@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
* *
* $Id: painting.c,v 1.66 2004/02/03 17:53:55 navaraf Exp $ * $Id: painting.c,v 1.67 2004/02/04 23:01:07 gvg Exp $
* *
* COPYRIGHT: See COPYING in the top level directory * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
@ -52,7 +52,7 @@
#include <include/intgdi.h> #include <include/intgdi.h>
#define NDEBUG #define NDEBUG
#include <debug.h> #include <win32k/debug1.h>
/* PRIVATE FUNCTIONS **********************************************************/ /* PRIVATE FUNCTIONS **********************************************************/
@ -68,6 +68,7 @@ IntValidateParent(PWINDOW_OBJECT Child, HRGN ValidRegion)
ParentWindow = IntGetWindowObject(Parent); ParentWindow = IntGetWindowObject(Parent);
if (ParentWindow && !(ParentWindow->Style & WS_CLIPCHILDREN)) if (ParentWindow && !(ParentWindow->Style & WS_CLIPCHILDREN))
{ {
ExAcquireFastMutex(&ParentWindow->UpdateLock);
if (ParentWindow->UpdateRegion != 0) if (ParentWindow->UpdateRegion != 0)
{ {
INT OffsetX, OffsetY; INT OffsetX, OffsetY;
@ -84,6 +85,7 @@ IntValidateParent(PWINDOW_OBJECT Child, HRGN ValidRegion)
/* FIXME: If the resulting region is empty, remove fake posted paint message */ /* FIXME: If the resulting region is empty, remove fake posted paint message */
NtGdiOffsetRgn(ValidRegion, -OffsetX, -OffsetY); NtGdiOffsetRgn(ValidRegion, -OffsetX, -OffsetY);
} }
ExReleaseFastMutex(&ParentWindow->UpdateLock);
} }
IntReleaseWindowObject(ParentWindow); IntReleaseWindowObject(ParentWindow);
Parent = NtUserGetAncestor(Parent, GA_PARENT); Parent = NtUserGetAncestor(Parent, GA_PARENT);
@ -104,12 +106,14 @@ IntValidateParent(PWINDOW_OBJECT Child, HRGN ValidRegion)
* as valid, clears the WINDOWOBJECT_NEED_NCPAINT flag. * as valid, clears the WINDOWOBJECT_NEED_NCPAINT flag.
*/ */
HRGN FASTCALL STATIC HRGN FASTCALL
IntGetNCUpdateRegion(PWINDOW_OBJECT Window) IntGetNCUpdateRegion(PWINDOW_OBJECT Window)
{ {
HRGN WindowRgn; HRGN WindowRgn;
HRGN NonclientRgn; HRGN NonclientRgn;
ASSERT(! ExTryToAcquireFastMutex(&Window->UpdateLock));
/* /*
* Generate the update region. * Generate the update region.
*/ */
@ -148,7 +152,7 @@ IntGetNCUpdateRegion(PWINDOW_OBJECT Window)
* Internal function used by IntRedrawWindow. * Internal function used by IntRedrawWindow.
*/ */
VOID FASTCALL STATIC VOID FASTCALL
IntPaintWindows(PWINDOW_OBJECT Window, ULONG Flags) IntPaintWindows(PWINDOW_OBJECT Window, ULONG Flags)
{ {
HDC hDC; HDC hDC;
@ -163,6 +167,7 @@ IntPaintWindows(PWINDOW_OBJECT Window, ULONG Flags)
{ {
if (Window->Flags & WINDOWOBJECT_NEED_NCPAINT) if (Window->Flags & WINDOWOBJECT_NEED_NCPAINT)
{ {
ExAcquireFastMutex(&Window->UpdateLock);
if (Window->NCUpdateRegion) if (Window->NCUpdateRegion)
{ {
IntValidateParent(Window, Window->NCUpdateRegion); IntValidateParent(Window, Window->NCUpdateRegion);
@ -171,6 +176,7 @@ IntPaintWindows(PWINDOW_OBJECT Window, ULONG Flags)
Window->NCUpdateRegion = NULL; Window->NCUpdateRegion = NULL;
Window->Flags &= ~WINDOWOBJECT_NEED_NCPAINT; Window->Flags &= ~WINDOWOBJECT_NEED_NCPAINT;
MsqDecPaintCountQueue(Window->MessageQueue); MsqDecPaintCountQueue(Window->MessageQueue);
ExReleaseFastMutex(&Window->UpdateLock);
} }
if (Window->Flags & WINDOWOBJECT_NEED_ERASEBKGND) if (Window->Flags & WINDOWOBJECT_NEED_ERASEBKGND)
@ -197,6 +203,7 @@ IntPaintWindows(PWINDOW_OBJECT Window, ULONG Flags)
Window->Flags & WINDOWOBJECT_NEED_INTERNALPAINT) Window->Flags & WINDOWOBJECT_NEED_INTERNALPAINT)
{ {
IntSendMessage(hWnd, WM_PAINT, 0, 0); IntSendMessage(hWnd, WM_PAINT, 0, 0);
ExAcquireFastMutex(&Window->UpdateLock);
if (Window->Flags & WINDOWOBJECT_NEED_INTERNALPAINT) if (Window->Flags & WINDOWOBJECT_NEED_INTERNALPAINT)
{ {
Window->Flags &= ~WINDOWOBJECT_NEED_INTERNALPAINT; Window->Flags &= ~WINDOWOBJECT_NEED_INTERNALPAINT;
@ -205,6 +212,7 @@ IntPaintWindows(PWINDOW_OBJECT Window, ULONG Flags)
MsqDecPaintCountQueue(Window->MessageQueue); MsqDecPaintCountQueue(Window->MessageQueue);
} }
} }
ExReleaseFastMutex(&Window->UpdateLock);
} }
} }
} }
@ -282,6 +290,7 @@ IntInvalidateWindows(PWINDOW_OBJECT Window, HRGN hRgn, ULONG Flags)
* Save current state of pending updates * Save current state of pending updates
*/ */
ExAcquireFastMutex(&Window->UpdateLock);
HadPaintMessage = Window->UpdateRegion != NULL || HadPaintMessage = Window->UpdateRegion != NULL ||
Window->Flags & WINDOWOBJECT_NEED_INTERNALPAINT; Window->Flags & WINDOWOBJECT_NEED_INTERNALPAINT;
HadNCPaintMessage = Window->Flags & WINDOWOBJECT_NEED_NCPAINT; HadNCPaintMessage = Window->Flags & WINDOWOBJECT_NEED_NCPAINT;
@ -418,6 +427,8 @@ IntInvalidateWindows(PWINDOW_OBJECT Window, HRGN hRgn, ULONG Flags)
else else
MsqIncPaintCountQueue(Window->MessageQueue); MsqIncPaintCountQueue(Window->MessageQueue);
} }
ExReleaseFastMutex(&Window->UpdateLock);
} }
/* /*
@ -614,15 +625,17 @@ IntGetPaintMessage(HWND hWnd, PW32THREAD Thread, MSG *Message,
#if 0 #if 0
DPRINT1("PAINTING BUG: Thread marked as containing dirty windows, but no dirty windows found!\n"); DPRINT1("PAINTING BUG: Thread marked as containing dirty windows, but no dirty windows found!\n");
#endif #endif
/* FIXME: Lock the queue! */ ExAcquireFastMutex(&MessageQueue->Lock);
MessageQueue->PaintPosted = 0; MessageQueue->PaintPosted = 0;
MessageQueue->PaintCount = 0; MessageQueue->PaintCount = 0;
ExReleaseFastMutex(&MessageQueue->Lock);
return FALSE; return FALSE;
} }
Window = IntGetWindowObject(Message->hwnd); Window = IntGetWindowObject(Message->hwnd);
if (Window != NULL) if (Window != NULL)
{ {
ExAcquireFastMutex(&Window->UpdateLock);
if (Window->Flags & WINDOWOBJECT_NEED_NCPAINT) if (Window->Flags & WINDOWOBJECT_NEED_NCPAINT)
{ {
Message->message = WM_NCPAINT; Message->message = WM_NCPAINT;
@ -647,6 +660,7 @@ IntGetPaintMessage(HWND hWnd, PW32THREAD Thread, MSG *Message,
} }
} }
} }
ExReleaseFastMutex(&Window->UpdateLock);
IntReleaseWindowObject(Window); IntReleaseWindowObject(Window);
return TRUE; return TRUE;
@ -724,6 +738,7 @@ NtUserBeginPaint(HWND hWnd, PAINTSTRUCT* lPs)
return NULL; return NULL;
} }
ExAcquireFastMutex(&Window->UpdateLock);
if (Window->UpdateRegion != NULL) if (Window->UpdateRegion != NULL)
{ {
MsqDecPaintCountQueue(Window->MessageQueue); MsqDecPaintCountQueue(Window->MessageQueue);
@ -739,6 +754,7 @@ NtUserBeginPaint(HWND hWnd, PAINTSTRUCT* lPs)
{ {
NtUserGetClientRect(Window, &lPs->rcPaint); NtUserGetClientRect(Window, &lPs->rcPaint);
} }
ExReleaseFastMutex(&Window->UpdateLock);
if (Window->Flags & WINDOWOBJECT_NEED_ERASEBKGND) if (Window->Flags & WINDOWOBJECT_NEED_ERASEBKGND)
{ {

View file

@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/ */
/* $Id: window.c,v 1.180 2004/02/04 01:10:25 rcampbell Exp $ /* $Id: window.c,v 1.181 2004/02/04 23:01:07 gvg Exp $
* *
* COPYRIGHT: See COPYING in the top level directory * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
@ -1251,6 +1251,7 @@ NtUserCreateWindowEx(DWORD dwExStyle,
InitializeListHead(&WindowObject->PropListHead); InitializeListHead(&WindowObject->PropListHead);
ExInitializeFastMutex(&WindowObject->PropListLock); ExInitializeFastMutex(&WindowObject->PropListLock);
ExInitializeFastMutex(&WindowObject->ChildrenListLock); ExInitializeFastMutex(&WindowObject->ChildrenListLock);
ExInitializeFastMutex(&WindowObject->UpdateLock);
RtlInitUnicodeString(&WindowObject->WindowName, WindowName.Buffer); RtlInitUnicodeString(&WindowObject->WindowName, WindowName.Buffer);