fixed a couple of dead-locks in the region code

svn path=/trunk/; revision=8838
This commit is contained in:
Thomas Bluemel 2004-03-22 20:14:29 +00:00
parent ccecaee56d
commit d8eb783e69
6 changed files with 117 additions and 69 deletions

View file

@ -151,9 +151,9 @@ NtGdiGetRegionData(HRGN hrgn,
HRGN STDCALL REGION_CropRgn(HRGN hDst, HRGN hSrc, const PRECT lpRect, PPOINT lpPt); HRGN STDCALL REGION_CropRgn(HRGN hDst, HRGN hSrc, const PRECT lpRect, PPOINT lpPt);
HRGN STDCALL UnsafeIntCreateRectRgnIndirect(CONST PRECT rc); HRGN FASTCALL UnsafeIntCreateRectRgnIndirect(CONST PRECT rc);
INT STDCALL UnsafeIntGetRgnBox(HRGN hRgn, LPRECT pRect); INT FASTCALL UnsafeIntGetRgnBox(PROSRGNDATA Rgn, LPRECT pRect);
HRGN FASTCALL UnsafeIntUnionRectWithRgn(HRGN hDest, CONST PRECT Rect); VOID FASTCALL UnsafeIntUnionRectWithRgn(PROSRGNDATA RgnDest, CONST PRECT Rect);
BOOL FASTCALL UnsafeIntRectInRegion(HRGN hRgn, CONST LPRECT rc); BOOL FASTCALL UnsafeIntRectInRegion(PROSRGNDATA Rgn, CONST LPRECT rc);
#endif #endif

View file

@ -60,6 +60,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;
/* Handle of the window region. */
HANDLE WindowRegion;
/* Lock to be held when manipulating (NC)UpdateRegion */ /* Lock to be held when manipulating (NC)UpdateRegion */
FAST_MUTEX UpdateLock; FAST_MUTEX UpdateLock;
/* Pointer to the owning thread's message queue. */ /* Pointer to the owning thread's message queue. */

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.76 2004/03/13 17:33:53 gvg Exp $ * $Id: painting.c,v 1.77 2004/03/22 20:14:29 weiden Exp $
* *
* COPYRIGHT: See COPYING in the top level directory * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
@ -212,12 +212,12 @@ IntInvalidateWindows(PWINDOW_OBJECT Window, HRGN hRgn, ULONG Flags)
* Clip the given region with window rectangle (or region) * Clip the given region with window rectangle (or region)
*/ */
#ifdef TODO IntLockWindowUpdate(Window);
if (!Window->WindowRegion) if (!Window->WindowRegion)
#endif
{ {
HRGN hRgnWindow; HRGN hRgnWindow;
IntUnLockWindowUpdate(Window);
hRgnWindow = UnsafeIntCreateRectRgnIndirect(&Window->WindowRect); hRgnWindow = UnsafeIntCreateRectRgnIndirect(&Window->WindowRect);
NtGdiOffsetRgn(hRgnWindow, NtGdiOffsetRgn(hRgnWindow,
-Window->WindowRect.left, -Window->WindowRect.left,
@ -225,12 +225,11 @@ IntInvalidateWindows(PWINDOW_OBJECT Window, HRGN hRgn, ULONG Flags)
RgnType = NtGdiCombineRgn(hRgn, hRgn, hRgnWindow, RGN_AND); RgnType = NtGdiCombineRgn(hRgn, hRgn, hRgnWindow, RGN_AND);
NtGdiDeleteObject(hRgnWindow); NtGdiDeleteObject(hRgnWindow);
} }
#ifdef TODO
else else
{ {
RgnType = NtGdiCombineRgn(hRgn, hRgn, Window->WindowRegion, RGN_AND); RgnType = NtGdiCombineRgn(hRgn, hRgn, Window->WindowRegion, RGN_AND);
IntUnLockWindowUpdate(Window);
} }
#endif
/* /*
* Save current state of pending updates * Save current state of pending updates

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: winpos.c,v 1.101 2004/02/26 22:23:55 weiden Exp $ /* $Id: winpos.c,v 1.102 2004/03/22 20:14:29 weiden Exp $
* *
* COPYRIGHT: See COPYING in the top level directory * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
@ -774,6 +774,7 @@ WinPosSetWindowPos(HWND Wnd, HWND WndInsertAfter, INT x, INT y, INT cx,
WINDOWPOS WinPos; WINDOWPOS WinPos;
RECT NewWindowRect; RECT NewWindowRect;
RECT NewClientRect; RECT NewClientRect;
PROSRGNDATA VisRgn;
HRGN VisBefore = NULL; HRGN VisBefore = NULL;
HRGN VisAfter = NULL; HRGN VisAfter = NULL;
HRGN DirtyRgn = NULL; HRGN DirtyRgn = NULL;
@ -845,13 +846,19 @@ WinPosSetWindowPos(HWND Wnd, HWND WndInsertAfter, INT x, INT y, INT cx,
(SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER)) (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER))
{ {
VisBefore = VIS_ComputeVisibleRegion(Window, FALSE, FALSE, TRUE); VisBefore = VIS_ComputeVisibleRegion(Window, FALSE, FALSE, TRUE);
VisRgn = NULL;
if (VisBefore != NULL && if (VisBefore != NULL && (VisRgn = (PROSRGNDATA)RGNDATA_LockRgn(VisBefore)) &&
UnsafeIntGetRgnBox(VisBefore, &TempRect) == NULLREGION) UnsafeIntGetRgnBox(VisRgn, &TempRect) == NULLREGION)
{ {
RGNDATA_UnlockRgn(VisBefore);
NtGdiDeleteObject(VisBefore); NtGdiDeleteObject(VisBefore);
VisBefore = NULL; VisBefore = NULL;
} }
else if(VisRgn)
{
RGNDATA_UnlockRgn(VisBefore);
}
} }
WvrFlags = WinPosDoNCCALCSize(Window, &WinPos, &NewWindowRect, &NewClientRect); WvrFlags = WinPosDoNCCALCSize(Window, &WinPos, &NewWindowRect, &NewClientRect);
@ -940,13 +947,19 @@ WinPosSetWindowPos(HWND Wnd, HWND WndInsertAfter, INT x, INT y, INT cx,
/* Determine the new visible region */ /* Determine the new visible region */
VisAfter = VIS_ComputeVisibleRegion(Window, FALSE, FALSE, TRUE); VisAfter = VIS_ComputeVisibleRegion(Window, FALSE, FALSE, TRUE);
VisRgn = NULL;
if (VisAfter != NULL && if (VisAfter != NULL && (VisRgn = (PROSRGNDATA)RGNDATA_LockRgn(VisAfter)) &&
UnsafeIntGetRgnBox(VisAfter, &TempRect) == NULLREGION) UnsafeIntGetRgnBox(VisRgn, &TempRect) == NULLREGION)
{ {
RGNDATA_UnlockRgn(VisAfter);
NtGdiDeleteObject(VisAfter); NtGdiDeleteObject(VisAfter);
VisAfter = NULL; VisAfter = NULL;
} }
else if(VisRgn)
{
RGNDATA_UnlockRgn(VisAfter);
}
/* /*
* Determine which pixels can be copied from the old window position * Determine which pixels can be copied from the old window position
@ -995,15 +1008,22 @@ WinPosSetWindowPos(HWND Wnd, HWND WndInsertAfter, INT x, INT y, INT cx,
* there's nothing to copy. Also, it's no use copying bits onto * there's nothing to copy. Also, it's no use copying bits onto
* themselves. * themselves.
*/ */
if (UnsafeIntGetRgnBox(CopyRgn, &CopyRect) == NULLREGION) VisRgn = NULL;
if ((VisRgn = (PROSRGNDATA)RGNDATA_LockRgn(CopyRgn)) &&
UnsafeIntGetRgnBox(VisRgn, &CopyRect) == NULLREGION)
{ {
/* Nothing to copy, clean up */ /* Nothing to copy, clean up */
RGNDATA_UnlockRgn(CopyRgn);
NtGdiDeleteObject(CopyRgn); NtGdiDeleteObject(CopyRgn);
CopyRgn = NULL; CopyRgn = NULL;
} }
else if (OldWindowRect.left != NewWindowRect.left || else if (OldWindowRect.left != NewWindowRect.left ||
OldWindowRect.top != NewWindowRect.top) OldWindowRect.top != NewWindowRect.top)
{ {
if(VisRgn)
{
RGNDATA_UnlockRgn(CopyRgn);
}
/* /*
* Small trick here: there is no function to bitblt a region. So * Small trick here: there is no function to bitblt a region. So
* we set the region as the clipping region, take the bounding box * we set the region as the clipping region, take the bounding box
@ -1026,6 +1046,10 @@ WinPosSetWindowPos(HWND Wnd, HWND WndInsertAfter, INT x, INT y, INT cx,
NtUserReleaseDC(Wnd, Dc); NtUserReleaseDC(Wnd, Dc);
IntValidateParent(Window, CopyRgn); IntValidateParent(Window, CopyRgn);
} }
else if(VisRgn)
{
RGNDATA_UnlockRgn(CopyRgn);
}
} }
else else
{ {

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: cliprgn.c,v 1.29 2003/12/21 18:38:37 navaraf Exp $ */ /* $Id: cliprgn.c,v 1.30 2004/03/22 20:14:29 weiden Exp $ */
#undef WIN32_LEAN_AND_MEAN #undef WIN32_LEAN_AND_MEAN
#include <windows.h> #include <windows.h>
@ -162,12 +162,19 @@ int FASTCALL
IntGdiGetClipBox(HDC hDC, IntGdiGetClipBox(HDC hDC,
LPRECT rc) LPRECT rc)
{ {
PROSRGNDATA Rgn;
int retval; int retval;
PDC dc; PDC dc;
if (!(dc = DC_LockDc(hDC))) if (!(dc = DC_LockDc(hDC)))
return ERROR; return ERROR;
retval = UnsafeIntGetRgnBox(dc->w.hGCClipRgn, rc); if(!(Rgn = RGNDATA_LockRgn(dc->w.hGCClipRgn)))
{
DC_UnlockDc( hDC );
return ERROR;
}
retval = UnsafeIntGetRgnBox(Rgn, rc);
RGNDATA_UnlockRgn(dc->w.hGCClipRgn);
IntDPtoLP(dc, (LPPOINT)rc, 2); IntDPtoLP(dc, (LPPOINT)rc, 2);
DC_UnlockDc( hDC ); DC_UnlockDc( hDC );
return(retval); return(retval);
@ -260,6 +267,8 @@ BOOL STDCALL NtGdiPtVisible(HDC hDC,
BOOL STDCALL NtGdiRectVisible(HDC hDC, BOOL STDCALL NtGdiRectVisible(HDC hDC,
CONST PRECT UnsafeRect) CONST PRECT UnsafeRect)
{ {
NTSTATUS Status;
PROSRGNDATA Rgn;
PDC dc = DC_LockDc(hDC); PDC dc = DC_LockDc(hDC);
BOOL Result = FALSE; BOOL Result = FALSE;
RECT Rect; RECT Rect;
@ -269,12 +278,21 @@ BOOL STDCALL NtGdiRectVisible(HDC hDC,
return FALSE; return FALSE;
} }
MmCopyFromCaller(&Rect, UnsafeRect, sizeof(RECT)); Status = MmCopyFromCaller(&Rect, UnsafeRect, sizeof(RECT));
if(!NT_SUCCESS(Status))
{
DC_UnlockDc(hDC);
return FALSE;
}
if (dc->w.hGCClipRgn) if (dc->w.hGCClipRgn)
{ {
IntLPtoDP(dc, (LPPOINT)&Rect, 2); if((Rgn = (PROSRGNDATA)RGNDATA_LockRgn(dc->w.hGCClipRgn)))
Result = UnsafeIntRectInRegion(dc->w.hGCClipRgn, &Rect); {
IntLPtoDP(dc, (LPPOINT)&Rect, 2);
Result = UnsafeIntRectInRegion(Rgn, &Rect);
RGNDATA_UnlockRgn(dc->w.hGCClipRgn);
}
} }
DC_UnlockDc(hDC); DC_UnlockDc(hDC);

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: region.c,v 1.42 2004/02/19 21:12:10 weiden Exp $ */ /* $Id: region.c,v 1.43 2004/03/22 20:14:29 weiden Exp $ */
#undef WIN32_LEAN_AND_MEAN #undef WIN32_LEAN_AND_MEAN
#include <windows.h> #include <windows.h>
#include <ddk/ntddk.h> #include <ddk/ntddk.h>
@ -1674,7 +1674,7 @@ NtGdiCreateRectRgnIndirect(CONST PRECT rc)
return(UnsafeIntCreateRectRgnIndirect(&SafeRc)); return(UnsafeIntCreateRectRgnIndirect(&SafeRc));
} }
HRGN STDCALL HRGN FASTCALL
UnsafeIntCreateRectRgnIndirect(CONST PRECT rc) UnsafeIntCreateRectRgnIndirect(CONST PRECT rc)
{ {
return(NtGdiCreateRectRgn(rc->left, rc->top, rc->right, rc->bottom)); return(NtGdiCreateRectRgn(rc->left, rc->top, rc->right, rc->bottom));
@ -1735,10 +1735,10 @@ NtGdiCreateRoundRectRgn(INT left, INT top, INT right, INT bottom,
/* move toward center */ /* move toward center */
rect.top = top++; rect.top = top++;
rect.bottom = rect.top + 1; rect.bottom = rect.top + 1;
UnsafeIntUnionRectWithRgn( hrgn, &rect ); UnsafeIntUnionRectWithRgn( obj, &rect );
rect.top = --bottom; rect.top = --bottom;
rect.bottom = rect.top + 1; rect.bottom = rect.top + 1;
UnsafeIntUnionRectWithRgn( hrgn, &rect ); UnsafeIntUnionRectWithRgn( obj, &rect );
yd -= 2*asq; yd -= 2*asq;
d -= yd; d -= yd;
} }
@ -1747,7 +1747,6 @@ NtGdiCreateRoundRectRgn(INT left, INT top, INT right, INT bottom,
xd += 2*bsq; xd += 2*bsq;
d += bsq + xd; d += bsq + xd;
} }
/* Loop to draw second half of quadrant */ /* Loop to draw second half of quadrant */
d += (3 * (asq-bsq) / 2 - (xd+yd)) / 2; d += (3 * (asq-bsq) / 2 - (xd+yd)) / 2;
@ -1756,10 +1755,10 @@ NtGdiCreateRoundRectRgn(INT left, INT top, INT right, INT bottom,
/* next vertical point */ /* next vertical point */
rect.top = top++; rect.top = top++;
rect.bottom = rect.top + 1; rect.bottom = rect.top + 1;
UnsafeIntUnionRectWithRgn( hrgn, &rect ); UnsafeIntUnionRectWithRgn( obj, &rect );
rect.top = --bottom; rect.top = --bottom;
rect.bottom = rect.top + 1; rect.bottom = rect.top + 1;
UnsafeIntUnionRectWithRgn( hrgn, &rect ); UnsafeIntUnionRectWithRgn( obj, &rect );
if (d < 0) /* if nearest pixel is outside ellipse */ if (d < 0) /* if nearest pixel is outside ellipse */
{ {
rect.left--; /* move away from center */ rect.left--; /* move away from center */
@ -1770,14 +1769,13 @@ NtGdiCreateRoundRectRgn(INT left, INT top, INT right, INT bottom,
yd -= 2*asq; yd -= 2*asq;
d += asq - yd; d += asq - yd;
} }
/* Add the inside rectangle */ /* Add the inside rectangle */
if (top <= bottom) if (top <= bottom)
{ {
rect.top = top; rect.top = top;
rect.bottom = bottom; rect.bottom = bottom;
UnsafeIntUnionRectWithRgn( hrgn, &rect ); UnsafeIntUnionRectWithRgn( obj, &rect );
} }
RGNDATA_UnlockRgn( hrgn ); RGNDATA_UnlockRgn( hrgn );
return hrgn; return hrgn;
@ -1888,18 +1886,16 @@ NtGdiFrameRgn(HDC hDC,
UNIMPLEMENTED; UNIMPLEMENTED;
} }
INT STDCALL INT FASTCALL
UnsafeIntGetRgnBox(HRGN hRgn, UnsafeIntGetRgnBox(PROSRGNDATA Rgn,
LPRECT pRect) LPRECT pRect)
{ {
PROSRGNDATA rgn = RGNDATA_LockRgn(hRgn);
DWORD ret; DWORD ret;
if (rgn) if (Rgn)
{ {
*pRect = rgn->rdh.rcBound; *pRect = Rgn->rdh.rcBound;
ret = rgn->rdh.iType; ret = Rgn->rdh.iType;
RGNDATA_UnlockRgn( hRgn );
return ret; return ret;
} }
@ -1911,10 +1907,17 @@ INT STDCALL
NtGdiGetRgnBox(HRGN hRgn, NtGdiGetRgnBox(HRGN hRgn,
LPRECT pRect) LPRECT pRect)
{ {
PROSRGNDATA Rgn;
RECT SafeRect; RECT SafeRect;
DWORD ret; DWORD ret;
ret = UnsafeIntGetRgnBox(hRgn, &SafeRect); if (!(Rgn = RGNDATA_LockRgn(hRgn)))
{
return ERROR;
}
ret = UnsafeIntGetRgnBox(Rgn, &SafeRect);
RGNDATA_UnlockRgn(hRgn);
if (ERROR == ret) if (ERROR == ret)
{ {
return ret; return ret;
@ -2066,31 +2069,25 @@ NtGdiPtInRegion(HRGN hRgn,
BOOL BOOL
FASTCALL FASTCALL
UnsafeIntRectInRegion(HRGN hRgn, UnsafeIntRectInRegion(PROSRGNDATA Rgn,
CONST LPRECT rc) CONST LPRECT rc)
{ {
PROSRGNDATA rgn;
PRECT pCurRect, pRectEnd; PRECT pCurRect, pRectEnd;
BOOL bRet = FALSE;
if( !( rgn = RGNDATA_LockRgn(hRgn) ) )
return ERROR;
// this is (just) a useful optimization // this is (just) a useful optimization
if((rgn->rdh.nCount > 0) && EXTENTCHECK(&rgn->rdh.rcBound, rc)) if((Rgn->rdh.nCount > 0) && EXTENTCHECK(&Rgn->rdh.rcBound, rc))
{ {
for (pCurRect = (PRECT)rgn->Buffer, pRectEnd = pCurRect + rgn->rdh.nCount; pCurRect < pRectEnd; pCurRect++) for (pCurRect = (PRECT)Rgn->Buffer, pRectEnd = pCurRect + Rgn->rdh.nCount; pCurRect < pRectEnd; pCurRect++)
{ {
if (pCurRect->bottom <= rc->top) continue; // not far enough down yet if (pCurRect->bottom <= rc->top) continue; // not far enough down yet
if (pCurRect->top >= rc->bottom) break; // too far down if (pCurRect->top >= rc->bottom) break; // too far down
if (pCurRect->right <= rc->left) continue; // not far enough over yet if (pCurRect->right <= rc->left) continue; // not far enough over yet
if (pCurRect->left >= rc->right) continue; if (pCurRect->left >= rc->right) continue;
bRet = TRUE;
break; return TRUE;
} }
} }
RGNDATA_UnlockRgn(hRgn); return FALSE;
return bRet;
} }
BOOL BOOL
@ -2098,15 +2095,25 @@ STDCALL
NtGdiRectInRegion(HRGN hRgn, NtGdiRectInRegion(HRGN hRgn,
CONST LPRECT unsaferc) CONST LPRECT unsaferc)
{ {
PROSRGNDATA Rgn;
RECT rc; RECT rc;
BOOL Ret;
if(!(Rgn = RGNDATA_LockRgn(hRgn)))
{
return ERROR;
}
if (!NT_SUCCESS(MmCopyFromCaller(&rc, unsaferc, sizeof(RECT)))) if (!NT_SUCCESS(MmCopyFromCaller(&rc, unsaferc, sizeof(RECT))))
{ {
RGNDATA_UnlockRgn(hRgn);
DPRINT1("NtGdiRectInRegion: bogus rc\n"); DPRINT1("NtGdiRectInRegion: bogus rc\n");
return ERROR; return ERROR;
} }
return UnsafeIntRectInRegion(hRgn, &rc); Ret = UnsafeIntRectInRegion(Rgn, &rc);
RGNDATA_UnlockRgn(hRgn);
return Ret;
} }
BOOL BOOL
@ -2145,36 +2152,34 @@ NtGdiSetRectRgn(HRGN hRgn,
return TRUE; return TRUE;
} }
HRGN FASTCALL VOID FASTCALL
UnsafeIntUnionRectWithRgn(HRGN hDest, CONST PRECT Rect) UnsafeIntUnionRectWithRgn(PROSRGNDATA RgnDest, CONST PRECT Rect)
{ {
PROSRGNDATA pRgn; REGION_UnionRectWithRegion(Rect, RgnDest);
pRgn = RGNDATA_LockRgn(hDest);
if (NULL == pRgn)
{
SetLastWin32Error(ERROR_INVALID_HANDLE);
return NULL;
}
REGION_UnionRectWithRegion(Rect, pRgn);
RGNDATA_UnlockRgn(hDest);
return hDest;
} }
HRGN STDCALL HRGN STDCALL
NtGdiUnionRectWithRgn(HRGN hDest, CONST PRECT UnsafeRect) NtGdiUnionRectWithRgn(HRGN hDest, CONST PRECT UnsafeRect)
{ {
RECT SafeRect; RECT SafeRect;
PROSRGNDATA Rgn;
if(!(Rgn = (PROSRGNDATA)RGNDATA_UnlockRgn(hDest)))
{
SetLastWin32Error(ERROR_INVALID_HANDLE);
return NULL;
}
if (! NT_SUCCESS(MmCopyFromCaller(&SafeRect, UnsafeRect, sizeof(RECT)))) if (! NT_SUCCESS(MmCopyFromCaller(&SafeRect, UnsafeRect, sizeof(RECT))))
{ {
RGNDATA_UnlockRgn(hDest);
SetLastWin32Error(ERROR_INVALID_PARAMETER); SetLastWin32Error(ERROR_INVALID_PARAMETER);
return NULL; return NULL;
} }
return UnsafeIntUnionRectWithRgn(hDest, &SafeRect); UnsafeIntUnionRectWithRgn(Rgn, &SafeRect);
RGNDATA_UnlockRgn(hDest);
return hDest;
} }
/*! /*!