- Slap *a bit* of sense in the way we use region objects and handles, avoiding a massive orgy of handle allocations, locks, leaks and so on.
The motto here being "if you don't need a valid user-mode handle, then chances are that you don't need one at all."
CORE-8506 #resolve #comment Stale region handles should not be passed anymore to user-mode apps now.

svn path=/trunk/; revision=64177
This commit is contained in:
Jérôme Gardou 2014-09-17 09:54:27 +00:00
parent 726e4806e9
commit 215e0d90a1
18 changed files with 600 additions and 508 deletions

View file

@ -52,15 +52,11 @@ IntEngWndUpdateClipObj(
XCLIPOBJ* Clip, XCLIPOBJ* Clip,
PWND Window) PWND Window)
{ {
HRGN hVisRgn;
PROSRGNDATA visRgn; PROSRGNDATA visRgn;
TRACE("IntEngWndUpdateClipObj\n"); TRACE("IntEngWndUpdateClipObj\n");
hVisRgn = VIS_ComputeVisibleRegion(Window, TRUE, TRUE, TRUE); visRgn = VIS_ComputeVisibleRegion(Window, TRUE, TRUE, TRUE);
if (hVisRgn != NULL)
{
visRgn = RGNOBJAPI_Lock(hVisRgn, NULL);
if (visRgn != NULL) if (visRgn != NULL)
{ {
if (visRgn->rdh.nCount > 0) if (visRgn->rdh.nCount > 0)
@ -80,13 +76,7 @@ IntEngWndUpdateClipObj(
} }
} }
} }
RGNOBJAPI_Unlock(visRgn); REGION_Delete(visRgn);
}
else
{
WARN("Couldn't lock visible region of window DC\n");
}
GreDeleteObject(hVisRgn);
} }
else else
{ {

View file

@ -477,7 +477,7 @@ NtGdiSelectClipPath(
HDC hDC, HDC hDC,
int Mode) int Mode)
{ {
HRGN hrgnPath; PREGION RgnPath;
PPATH pPath; PPATH pPath;
BOOL success = FALSE; BOOL success = FALSE;
PDC_ATTR pdcattr; PDC_ATTR pdcattr;
@ -507,20 +507,30 @@ NtGdiSelectClipPath(
} }
/* Construct a region from the path */ /* Construct a region from the path */
else if (PATH_PathToRegion(pPath, pdcattr->jFillMode, &hrgnPath)) RgnPath = IntSysCreateRectpRgn(0, 0, 0, 0);
if (!RgnPath)
{ {
PREGION prgnPath = REGION_LockRgn(hrgnPath); EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
ASSERT(prgnPath); DC_UnlockDc(pdc);
success = IntGdiExtSelectClipRgn(pdc, prgnPath, Mode) != ERROR; return FALSE;
REGION_UnlockRgn(prgnPath); }
GreDeleteObject( hrgnPath );
if (!PATH_PathToRegion(pPath, pdcattr->jFillMode, RgnPath))
{
EngSetLastError(ERROR_CAN_NOT_COMPLETE);
REGION_Delete(RgnPath);
DC_UnlockDc(pdc);
return FALSE;
}
success = IntGdiExtSelectClipRgn(pdc, RgnPath, Mode) != ERROR;
REGION_Delete(RgnPath);
/* Empty the path */ /* Empty the path */
if (success) if (success)
PATH_EmptyPath(pPath); PATH_EmptyPath(pPath);
/* FIXME: Should this function delete the path even if it failed? */ /* FIXME: Should this function delete the path even if it failed? */
}
PATH_UnlockPath(pPath); PATH_UnlockPath(pPath);
DC_UnlockDc(pdc); DC_UnlockDc(pdc);

View file

@ -458,8 +458,24 @@ NtGdiPolyPolyDraw( IN HDC hDC,
/* Special handling for GdiPolyPolyRgn */ /* Special handling for GdiPolyPolyRgn */
if (iFunc == GdiPolyPolyRgn) if (iFunc == GdiPolyPolyRgn)
{ {
PREGION Rgn;
HRGN hRgn; HRGN hRgn;
hRgn = IntCreatePolyPolygonRgn(SafePoints, SafeCounts, Count, (INT_PTR)hDC);
Rgn = REGION_AllocUserRgnWithHandle(0);
if (!Rgn)
{
EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
ExFreePoolWithTag(pTemp, TAG_SHAPE);
return 0;
}
hRgn = Rgn->BaseObject.hHmgr;
if (!IntSetPolyPolygonRgn(SafePoints, SafeCounts, Count, hDC ? 1 : 2, Rgn))
{
/* EngSetLastError ? */
GreDeleteObject(hRgn);
hRgn = NULL;
}
RGNOBJAPI_Unlock(Rgn);
ExFreePoolWithTag(pTemp, TAG_SHAPE); ExFreePoolWithTag(pTemp, TAG_SHAPE);
return (ULONG_PTR)hRgn; return (ULONG_PTR)hRgn;
} }

View file

@ -98,7 +98,7 @@ PATH_FillPath(
//SIZE ptViewportExt, ptWindowExt; //SIZE ptViewportExt, ptWindowExt;
//POINTL ptViewportOrg, ptWindowOrg; //POINTL ptViewportOrg, ptWindowOrg;
XFORM xform; XFORM xform;
HRGN hrgn; PREGION Rgn;
PDC_ATTR pdcattr = dc->pdcattr; PDC_ATTR pdcattr = dc->pdcattr;
if (pPath->state != PATH_Closed) if (pPath->state != PATH_Closed)
@ -107,8 +107,21 @@ PATH_FillPath(
return FALSE; return FALSE;
} }
if (PATH_PathToRegion(pPath, pdcattr->jFillMode, &hrgn)) /* Allocate a temporary region */
Rgn = IntSysCreateRectpRgn(0, 0, 0, 0);
if (!Rgn)
{ {
EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
return FALSE;
}
if (!PATH_PathToRegion(pPath, pdcattr->jFillMode, Rgn))
{
/* EngSetLastError ? */
REGION_Delete(Rgn);
return FALSE;
}
/* Since PaintRgn interprets the region as being in logical coordinates /* Since PaintRgn interprets the region as being in logical coordinates
* but the points we store for the path are already in device * but the points we store for the path are already in device
* coordinates, we have to set the mapping mode to MM_TEXT temporarily. * coordinates, we have to set the mapping mode to MM_TEXT temporarily.
@ -145,8 +158,8 @@ PATH_FillPath(
// pdcattr->iGraphicsMode = graphicsMode; // pdcattr->iGraphicsMode = graphicsMode;
/* Paint the region */ /* Paint the region */
IntGdiPaintRgn(dc, hrgn); IntGdiPaintRgn(dc, Rgn);
GreDeleteObject(hrgn); REGION_Delete(Rgn);
/* Restore the old mapping mode */ /* Restore the old mapping mode */
// IntGdiSetMapMode(dc, mapMode); // IntGdiSetMapMode(dc, mapMode);
// pdcattr->szlViewportExt = ptViewportExt; // pdcattr->szlViewportExt = ptViewportExt;
@ -160,8 +173,6 @@ PATH_FillPath(
// IntGdiModifyWorldTransform(dc, &xform, MWT_MAX+1); // IntGdiModifyWorldTransform(dc, &xform, MWT_MAX+1);
// pdcattr->iGraphicsMode = graphicsMode; // pdcattr->iGraphicsMode = graphicsMode;
return TRUE; return TRUE;
}
return FALSE;
} }
/* PATH_InitGdiPath /* PATH_InitGdiPath
@ -1221,14 +1232,14 @@ FASTCALL
PATH_PathToRegion( PATH_PathToRegion(
PPATH pPath, PPATH pPath,
INT nPolyFillMode, INT nPolyFillMode,
HRGN *pHrgn) PREGION Rgn)
{ {
int numStrokes, iStroke, i; int numStrokes, iStroke, i;
PULONG pNumPointsInStroke; PULONG pNumPointsInStroke;
HRGN hrgn = 0; BOOL Ret;
ASSERT(pPath != NULL); ASSERT(pPath != NULL);
ASSERT(pHrgn != NULL); ASSERT(Rgn != NULL);
PATH_FlattenPath(pPath); PATH_FlattenPath(pPath);
@ -1268,23 +1279,18 @@ PATH_PathToRegion(
pNumPointsInStroke[iStroke]++; pNumPointsInStroke[iStroke]++;
} }
/* Create a region from the strokes */ /* Fill the region with the strokes */
hrgn = IntCreatePolyPolygonRgn(pPath->pPoints, Ret = IntSetPolyPolygonRgn(pPath->pPoints,
pNumPointsInStroke, pNumPointsInStroke,
numStrokes, numStrokes,
nPolyFillMode); nPolyFillMode,
if (hrgn == (HRGN)0) Rgn);
{
EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
return FALSE;
}
/* Free memory for number-of-points-in-stroke array */ /* Free memory for number-of-points-in-stroke array */
ExFreePoolWithTag(pNumPointsInStroke, TAG_PATH); ExFreePoolWithTag(pNumPointsInStroke, TAG_PATH);
/* Success! */ /* Success! */
*pHrgn = hrgn; return Ret;
return TRUE;
} }
/* PATH_EmptyPath /* PATH_EmptyPath
@ -2675,6 +2681,7 @@ NtGdiPathToRegion(HDC hDC)
{ {
PPATH pPath; PPATH pPath;
HRGN hrgnRval = 0; HRGN hrgnRval = 0;
PREGION Rgn;
DC *pDc; DC *pDc;
PDC_ATTR pdcattr; PDC_ATTR pdcattr;
@ -2703,10 +2710,26 @@ NtGdiPathToRegion(HDC hDC)
} }
else else
{ {
/* Create the region and fill it with the path strokes */
Rgn = REGION_AllocUserRgnWithHandle(1);
if (!Rgn)
{
PATH_UnlockPath(pPath);
DC_UnlockDc(pDc);
}
hrgnRval = Rgn->BaseObject.hHmgr;
/* FIXME: Should we empty the path even if conversion failed? */ /* FIXME: Should we empty the path even if conversion failed? */
if (PATH_PathToRegion(pPath, pdcattr->jFillMode, &hrgnRval)) if (PATH_PathToRegion(pPath, pdcattr->jFillMode, Rgn))
{
PATH_EmptyPath(pPath); PATH_EmptyPath(pPath);
} }
else
{
GreDeleteObject(hrgnRval);
hrgnRval = NULL;
}
RGNOBJAPI_Unlock(Rgn);
}
PATH_UnlockPath(pPath); PATH_UnlockPath(pPath);
DC_UnlockDc(pDc); DC_UnlockDc(pDc);

View file

@ -67,7 +67,7 @@ BOOL FASTCALL PATH_PolyPolygon ( PDC dc, const POINT* pts, const INT* counts, UI
BOOL FASTCALL PATH_PolyPolyline( PDC dc, const POINT* pts, const DWORD* counts, DWORD polylines); BOOL FASTCALL PATH_PolyPolyline( PDC dc, const POINT* pts, const DWORD* counts, DWORD polylines);
BOOL FASTCALL PATH_Rectangle (PDC dc, INT x1, INT y1, INT x2, INT y2); BOOL FASTCALL PATH_Rectangle (PDC dc, INT x1, INT y1, INT x2, INT y2);
BOOL FASTCALL PATH_RoundRect(DC *dc, INT x1, INT y1, INT x2, INT y2, INT ell_width, INT ell_height); BOOL FASTCALL PATH_RoundRect(DC *dc, INT x1, INT y1, INT x2, INT y2, INT ell_width, INT ell_height);
BOOL FASTCALL PATH_PathToRegion (PPATH pPath, INT nPolyFillMode, HRGN *pHrgn); BOOL FASTCALL PATH_PathToRegion (PPATH pPath, INT nPolyFillMode, PREGION Rgn);
BOOL FASTCALL PATH_ExtTextOut(PDC dc,INT x,INT y,UINT flags,const RECTL *lprc,LPCWSTR str,UINT count,const INT *dx); BOOL FASTCALL PATH_ExtTextOut(PDC dc,INT x,INT y,UINT flags,const RECTL *lprc,LPCWSTR str,UINT count,const INT *dx);
BOOL FASTCALL PATH_AddEntry (PPATH pPath, const POINT *pPoint, BYTE flags); BOOL FASTCALL PATH_AddEntry (PPATH pPath, const POINT *pPoint, BYTE flags);

View file

@ -1956,46 +1956,35 @@ REGION_CreateFrameRgn(
} }
static
BOOL FASTCALL BOOL FASTCALL
REGION_LPTODP( REGION_LPTODP(
PDC dc, _In_ PDC dc,
HRGN hDest, _Inout_ PREGION RgnDest,
HRGN hSrc) _In_ PREGION RgnSrc)
{ {
RECTL *pCurRect, *pEndRect; RECTL *pCurRect, *pEndRect;
PROSRGNDATA srcObj = NULL;
PROSRGNDATA destObj = NULL;
RECTL tmpRect; RECTL tmpRect;
BOOL ret = FALSE;
PDC_ATTR pdcattr; PDC_ATTR pdcattr;
if (!dc) if (!dc)
return ret; return FALSE;
pdcattr = dc->pdcattr; pdcattr = dc->pdcattr;
if (pdcattr->iMapMode == MM_TEXT) // Requires only a translation if (pdcattr->iMapMode == MM_TEXT) // Requires only a translation
{ {
if (NtGdiCombineRgn(hDest, hSrc, 0, RGN_COPY) == ERROR) if (IntGdiCombineRgn(RgnDest, RgnSrc, 0, RGN_COPY) == ERROR)
goto done; return FALSE;
NtGdiOffsetRgn(hDest, pdcattr->ptlViewportOrg.x - pdcattr->ptlWindowOrg.x, IntGdiOffsetRgn(RgnDest, pdcattr->ptlViewportOrg.x - pdcattr->ptlWindowOrg.x,
pdcattr->ptlViewportOrg.y - pdcattr->ptlWindowOrg.y); pdcattr->ptlViewportOrg.y - pdcattr->ptlWindowOrg.y);
ret = TRUE; return TRUE;
goto done;
} }
if ( !(srcObj = RGNOBJAPI_Lock(hSrc, NULL)) ) EMPTY_REGION(RgnDest);
goto done;
if ( !(destObj = RGNOBJAPI_Lock(hDest, NULL)) )
{
RGNOBJAPI_Unlock(srcObj);
goto done;
}
EMPTY_REGION(destObj);
pEndRect = srcObj->Buffer + srcObj->rdh.nCount; pEndRect = RgnSrc->Buffer + RgnSrc->rdh.nCount;
for (pCurRect = srcObj->Buffer; pCurRect < pEndRect; pCurRect++) for (pCurRect = RgnSrc->Buffer; pCurRect < pEndRect; pCurRect++)
{ {
tmpRect = *pCurRect; tmpRect = *pCurRect;
tmpRect.left = XLPTODP(pdcattr, tmpRect.left); tmpRect.left = XLPTODP(pdcattr, tmpRect.left);
@ -2016,15 +2005,10 @@ REGION_LPTODP(
tmpRect.bottom = tmp; tmpRect.bottom = tmp;
} }
REGION_UnionRectWithRgn(destObj, &tmpRect); REGION_UnionRectWithRgn(RgnDest, &tmpRect);
} }
ret = TRUE;
RGNOBJAPI_Unlock(srcObj); return TRUE;
RGNOBJAPI_Unlock(destObj);
done:
return ret;
} }
PROSRGNDATA PROSRGNDATA
@ -2236,7 +2220,7 @@ IntSysCreateRectpRgn(INT LeftRect, INT TopRect, INT RightRect, INT BottomRect)
PREGION prgn; PREGION prgn;
/* Allocate a region, witout a handle */ /* Allocate a region, witout a handle */
prgn = (PREGION)GDIOBJ_AllocateObject(GDIObjType_RGN_TYPE, sizeof(REGION), 0); prgn = (PREGION)GDIOBJ_AllocateObject(GDIObjType_RGN_TYPE, sizeof(REGION), BASEFLAG_LOOKASIDE);
if (!prgn) if (!prgn)
{ {
return NULL; return NULL;
@ -2250,31 +2234,6 @@ IntSysCreateRectpRgn(INT LeftRect, INT TopRect, INT RightRect, INT BottomRect)
return prgn; return prgn;
} }
HRGN
FASTCALL
IntSysCreateRectRgn(INT LeftRect, INT TopRect, INT RightRect, INT BottomRect)
{
PREGION prgn;
HRGN hrgn;
/* Allocate a region, witout a handle */
prgn = (PREGION)GDIOBJ_AllocObjWithHandle(GDI_OBJECT_TYPE_REGION, sizeof(REGION));
if (!prgn)
{
return NULL;
}
/* Initialize it */
prgn->Buffer = &prgn->rdh.rcBound;
REGION_SetRectRgn(prgn, LeftRect, TopRect, RightRect, BottomRect);
hrgn = prgn->BaseObject.hHmgr;
prgn->prgnattr = &prgn->rgnattr;
REGION_UnlockRgn(prgn);
return hrgn;
}
VOID NTAPI VOID NTAPI
REGION_vCleanup(PVOID ObjectBody) REGION_vCleanup(PVOID ObjectBody)
{ {
@ -2479,44 +2438,42 @@ BOOL
FASTCALL FASTCALL
IntGdiPaintRgn( IntGdiPaintRgn(
PDC dc, PDC dc,
HRGN hRgn PREGION Rgn
) )
{ {
HRGN tmpVisRgn; PROSRGNDATA VisRgn;
PROSRGNDATA visrgn;
XCLIPOBJ ClipRegion; XCLIPOBJ ClipRegion;
BOOL bRet = FALSE; BOOL bRet = FALSE;
POINTL BrushOrigin; POINTL BrushOrigin;
SURFACE *psurf; SURFACE *psurf;
PDC_ATTR pdcattr; PDC_ATTR pdcattr;
if (!dc) return FALSE; if (!dc || !Rgn)
return FALSE;
pdcattr = dc->pdcattr; pdcattr = dc->pdcattr;
ASSERT(!(pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY))); ASSERT(!(pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY)));
if (!(tmpVisRgn = IntSysCreateRectRgn(0, 0, 0, 0))) return FALSE; VisRgn = IntSysCreateRectpRgn(0, 0, 0, 0);
if (!VisRgn)
// Transform region into device co-ords
if (!REGION_LPTODP(dc, tmpVisRgn, hRgn) ||
NtGdiOffsetRgn(tmpVisRgn, dc->ptlDCOrig.x, dc->ptlDCOrig.y) == ERROR)
{ {
GreDeleteObject(tmpVisRgn);
return FALSE; return FALSE;
} }
visrgn = RGNOBJAPI_Lock(tmpVisRgn, NULL); // Transform region into device co-ords
if (visrgn == NULL) if (!REGION_LPTODP(dc, VisRgn, Rgn) ||
IntGdiOffsetRgn(VisRgn, dc->ptlDCOrig.x, dc->ptlDCOrig.y) == ERROR)
{ {
GreDeleteObject(tmpVisRgn); REGION_Delete(VisRgn);
return FALSE; return FALSE;
} }
if (dc->prgnRao) if (dc->prgnRao)
IntGdiCombineRgn(visrgn, visrgn, dc->prgnRao, RGN_AND); IntGdiCombineRgn(VisRgn, VisRgn, dc->prgnRao, RGN_AND);
IntEngInitClipObj(&ClipRegion); IntEngInitClipObj(&ClipRegion);
IntEngUpdateClipRegion(&ClipRegion, visrgn->rdh.nCount, visrgn->Buffer, &visrgn->rdh.rcBound ); IntEngUpdateClipRegion(&ClipRegion, VisRgn->rdh.nCount, VisRgn->Buffer, &VisRgn->rdh.rcBound );
BrushOrigin.x = pdcattr->ptlBrushOrigin.x; BrushOrigin.x = pdcattr->ptlBrushOrigin.x;
BrushOrigin.y = pdcattr->ptlBrushOrigin.y; BrushOrigin.y = pdcattr->ptlBrushOrigin.y;
@ -2529,8 +2486,7 @@ IntGdiPaintRgn(
&BrushOrigin, &BrushOrigin,
0xFFFF); // FIXME: Don't know what to put here 0xFFFF); // FIXME: Don't know what to put here
RGNOBJAPI_Unlock(visrgn); REGION_Delete(VisRgn);
GreDeleteObject(tmpVisRgn);
IntEngFreeClipResources(&ClipRegion); IntEngFreeClipResources(&ClipRegion);
// Fill the region // Fill the region
@ -3129,16 +3085,15 @@ REGION_CreateETandAET(
} }
} }
HRGN FASTCALL BOOL FASTCALL
IntCreatePolyPolygonRgn( IntSetPolyPolygonRgn(
POINT *Pts, POINT *Pts,
PULONG Count, PULONG Count,
INT nbpolygons, INT nbpolygons,
INT mode INT mode,
PREGION Rgn
) )
{ {
HRGN hrgn;
ROSRGNDATA *region;
EdgeTableEntry *pAET; /* Active Edge Table */ EdgeTableEntry *pAET; /* Active Edge Table */
INT y; /* Current scanline */ INT y; /* Current scanline */
int iPts = 0; /* Number of pts in buffer */ int iPts = 0; /* Number of pts in buffer */
@ -3158,10 +3113,6 @@ IntCreatePolyPolygonRgn(
if (mode == 0 || mode > 2) return 0; if (mode == 0 || mode > 2) return 0;
if (!(region = REGION_AllocUserRgnWithHandle(nbpolygons)))
return 0;
hrgn = region->BaseObject.hHmgr;
/* Special case a rectangle */ /* Special case a rectangle */
if (((nbpolygons == 1) && ((*Count == 4) || if (((nbpolygons == 1) && ((*Count == 4) ||
@ -3175,18 +3126,19 @@ IntCreatePolyPolygonRgn(
(Pts[2].x == Pts[3].x) && (Pts[2].x == Pts[3].x) &&
(Pts[3].y == Pts[0].y)))) (Pts[3].y == Pts[0].y))))
{ {
RGNOBJAPI_Unlock(region); REGION_SetRectRgn(Rgn,
NtGdiSetRectRgn(hrgn, min(Pts[0].x, Pts[2].x), min(Pts[0].y, Pts[2].y), min(Pts[0].x, Pts[2].x),
max(Pts[0].x, Pts[2].x), max(Pts[0].y, Pts[2].y)); min(Pts[0].y, Pts[2].y),
return hrgn; max(Pts[0].x, Pts[2].x),
max(Pts[0].y, Pts[2].y));
return TRUE;
} }
for (poly = total = 0; poly < nbpolygons; poly++) for (poly = total = 0; poly < nbpolygons; poly++)
total += Count[poly]; total += Count[poly];
if (! (pETEs = ExAllocatePoolWithTag(PagedPool, sizeof(EdgeTableEntry) * total, TAG_REGION)) ) if (! (pETEs = ExAllocatePoolWithTag(PagedPool, sizeof(EdgeTableEntry) * total, TAG_REGION)) )
{ {
GreDeleteObject(hrgn); return FALSE;
return 0;
} }
pts = FirstPtBlock.pts; pts = FirstPtBlock.pts;
REGION_CreateETandAET(Count, nbpolygons, Pts, &ET, &AET, pETEs, &SLLBlock); REGION_CreateETandAET(Count, nbpolygons, Pts, &ET, &AET, pETEs, &SLLBlock);
@ -3230,7 +3182,7 @@ IntCreatePolyPolygonRgn(
{ {
DPRINT1("Can't alloc tPB\n"); DPRINT1("Can't alloc tPB\n");
ExFreePoolWithTag(pETEs, TAG_REGION); ExFreePoolWithTag(pETEs, TAG_REGION);
return 0; return FALSE;
} }
curPtBlock->next = tmpPtBlock; curPtBlock->next = tmpPtBlock;
curPtBlock = tmpPtBlock; curPtBlock = tmpPtBlock;
@ -3289,8 +3241,7 @@ IntCreatePolyPolygonRgn(
{ {
DPRINT1("Can't alloc tPB\n"); DPRINT1("Can't alloc tPB\n");
ExFreePoolWithTag(pETEs, TAG_REGION); ExFreePoolWithTag(pETEs, TAG_REGION);
GreDeleteObject(hrgn); return FALSE;
return 0;
} }
curPtBlock->next = tmpPtBlock; curPtBlock->next = tmpPtBlock;
curPtBlock = tmpPtBlock; curPtBlock = tmpPtBlock;
@ -3315,7 +3266,7 @@ IntCreatePolyPolygonRgn(
} }
} }
REGION_FreeStorage(SLLBlock.next); REGION_FreeStorage(SLLBlock.next);
REGION_PtsToRegion(numFullPtBlocks, iPts, &FirstPtBlock, region); REGION_PtsToRegion(numFullPtBlocks, iPts, &FirstPtBlock, Rgn);
for (curPtBlock = FirstPtBlock.next; --numFullPtBlocks >= 0;) for (curPtBlock = FirstPtBlock.next; --numFullPtBlocks >= 0;)
{ {
@ -3324,8 +3275,7 @@ IntCreatePolyPolygonRgn(
curPtBlock = tmpPtBlock; curPtBlock = tmpPtBlock;
} }
ExFreePoolWithTag(pETEs, TAG_REGION); ExFreePoolWithTag(pETEs, TAG_REGION);
RGNOBJAPI_Unlock(region); return TRUE;
return hrgn;
} }
BOOL BOOL
@ -3432,6 +3382,8 @@ NtGdiCreateRectRgn(INT LeftRect, INT TopRect, INT RightRect, INT BottomRect)
REGION_SetRectRgn(pRgn, LeftRect, TopRect, RightRect, BottomRect); REGION_SetRectRgn(pRgn, LeftRect, TopRect, RightRect, BottomRect);
RGNOBJAPI_Unlock(pRgn); RGNOBJAPI_Unlock(pRgn);
DPRINT1("Returning %p.\n", hRgn);
return hRgn; return hRgn;
} }
@ -3762,7 +3714,7 @@ NtGdiFrameRgn(
HRGN FrameRgn; HRGN FrameRgn;
BOOL Ret; BOOL Ret;
if (!(FrameRgn = IntSysCreateRectRgn(0, 0, 0, 0))) if (!(FrameRgn = NtGdiCreateRectRgn(0, 0, 0, 0)))
{ {
return FALSE; return FALSE;
} }

View file

@ -40,8 +40,8 @@ VOID FASTCALL IntGdiReleaseRaoRgn(PDC);
VOID FASTCALL IntGdiReleaseVisRgn(PDC); VOID FASTCALL IntGdiReleaseVisRgn(PDC);
INT APIENTRY IntGdiGetRgnBox(HRGN, RECTL*); INT APIENTRY IntGdiGetRgnBox(HRGN, RECTL*);
BOOL FASTCALL IntGdiPaintRgn(PDC, HRGN ); BOOL FASTCALL IntGdiPaintRgn(PDC, PREGION );
HRGN FASTCALL IntCreatePolyPolygonRgn(PPOINT, PULONG, INT, INT); BOOL FASTCALL IntSetPolyPolygonRgn(PPOINT, PULONG, INT, INT, PREGION);
INT FASTCALL IntGdiOffsetRgn(PROSRGNDATA,INT,INT); INT FASTCALL IntGdiOffsetRgn(PROSRGNDATA,INT,INT);
BOOL FASTCALL IntRectInRegion(HRGN,LPRECTL); BOOL FASTCALL IntRectInRegion(HRGN,LPRECTL);
@ -49,13 +49,9 @@ INT FASTCALL IntGdiCombineRgn(PROSRGNDATA, PROSRGNDATA, PROSRGNDATA, INT);
INT FASTCALL REGION_Complexity(PROSRGNDATA); INT FASTCALL REGION_Complexity(PROSRGNDATA);
PROSRGNDATA FASTCALL RGNOBJAPI_Lock(HRGN,PRGN_ATTR *); PROSRGNDATA FASTCALL RGNOBJAPI_Lock(HRGN,PRGN_ATTR *);
VOID FASTCALL RGNOBJAPI_Unlock(PROSRGNDATA); VOID FASTCALL RGNOBJAPI_Unlock(PROSRGNDATA);
HRGN FASTCALL IntSysCreateRectRgn(INT,INT,INT,INT);
PROSRGNDATA FASTCALL IntSysCreateRectpRgn(INT,INT,INT,INT); PROSRGNDATA FASTCALL IntSysCreateRectpRgn(INT,INT,INT,INT);
BOOL FASTCALL IntGdiSetRegionOwner(HRGN,DWORD); BOOL FASTCALL IntGdiSetRegionOwner(HRGN,DWORD);
#define IntSysCreateRectRgnIndirect(prc) \
IntSysCreateRectRgn((prc)->left, (prc)->top, (prc)->right, (prc)->bottom)
#define IntSysCreateRectpRgnIndirect(prc) \ #define IntSysCreateRectpRgnIndirect(prc) \
IntSysCreateRectpRgn((prc)->left, (prc)->top, (prc)->right, (prc)->bottom) IntSysCreateRectpRgn((prc)->left, (prc)->top, (prc)->right, (prc)->bottom)

View file

@ -1010,16 +1010,20 @@ IntDefWindowProc(
case WM_SYNCPAINT: case WM_SYNCPAINT:
{ {
HRGN hRgn; PREGION Rgn;
Wnd->state &= ~WNDS_SYNCPAINTPENDING; Wnd->state &= ~WNDS_SYNCPAINTPENDING;
ERR("WM_SYNCPAINT\n"); ERR("WM_SYNCPAINT\n");
hRgn = IntSysCreateRectRgn(0, 0, 0, 0); Rgn = IntSysCreateRectpRgn(0, 0, 0, 0);
if (co_UserGetUpdateRgn(Wnd, hRgn, FALSE) != NULLREGION) if (Rgn)
{ {
if (!wParam) wParam = (RDW_ERASENOW | RDW_ERASE | RDW_FRAME | RDW_ALLCHILDREN); if (co_UserGetUpdateRgn(Wnd, Rgn, FALSE) != NULLREGION)
co_UserRedrawWindow(Wnd, NULL, hRgn, wParam); {
if (!wParam)
wParam = (RDW_ERASENOW | RDW_ERASE | RDW_FRAME | RDW_ALLCHILDREN);
co_UserRedrawWindow(Wnd, NULL, Rgn, wParam);
}
REGION_Delete(Rgn);
} }
GreDeleteObject(hRgn);
return 0; return 0;
} }

View file

@ -752,19 +752,19 @@ VOID APIENTRY
UserRedrawDesktop() UserRedrawDesktop()
{ {
PWND Window = NULL; PWND Window = NULL;
HRGN hRgn; PREGION Rgn;
Window = UserGetDesktopWindow(); Window = UserGetDesktopWindow();
hRgn = IntSysCreateRectRgnIndirect(&Window->rcWindow); Rgn = IntSysCreateRectpRgnIndirect(&Window->rcWindow);
IntInvalidateWindows( Window, IntInvalidateWindows( Window,
hRgn, Rgn,
RDW_FRAME | RDW_FRAME |
RDW_ERASE | RDW_ERASE |
RDW_INVALIDATE | RDW_INVALIDATE |
RDW_ALLCHILDREN); RDW_ALLCHILDREN);
GreDeleteObject(hRgn); REGION_Delete(Rgn);
} }

View file

@ -652,7 +652,6 @@ IntDispatchMessage(PMSG pMsg)
LRESULT retval = 0; LRESULT retval = 0;
PTHREADINFO pti; PTHREADINFO pti;
PWND Window = NULL; PWND Window = NULL;
HRGN hrgn;
BOOL DoCallBack = TRUE; BOOL DoCallBack = TRUE;
if (pMsg->hwnd) if (pMsg->hwnd)
@ -743,11 +742,12 @@ IntDispatchMessage(PMSG pMsg)
if (pMsg->message == WM_PAINT) if (pMsg->message == WM_PAINT)
{ {
PREGION Rgn;
Window->state2 &= ~WNDS2_WMPAINTSENT; Window->state2 &= ~WNDS2_WMPAINTSENT;
/* send a WM_NCPAINT and WM_ERASEBKGND if the non-client area is still invalid */ /* send a WM_NCPAINT and WM_ERASEBKGND if the non-client area is still invalid */
hrgn = IntSysCreateRectRgn( 0, 0, 0, 0 ); Rgn = IntSysCreateRectpRgn( 0, 0, 0, 0 );
co_UserGetUpdateRgn( Window, hrgn, TRUE ); co_UserGetUpdateRgn( Window, Rgn, TRUE );
GreDeleteObject(hrgn); REGION_Delete(Rgn);
} }
return retval; return retval;

View file

@ -258,7 +258,11 @@ UserUpdateMonitorSize(IN HDEV hDev)
} }
/* ...and create new one */ /* ...and create new one */
pMonitor->hrgnMonitor = IntSysCreateRectRgnIndirect(&pMonitor->rcMonitor); pMonitor->hrgnMonitor = NtGdiCreateRectRgn(
pMonitor->rcMonitor.left,
pMonitor->rcMonitor.top,
pMonitor->rcMonitor.right,
pMonitor->rcMonitor.bottom);
if (pMonitor->hrgnMonitor) if (pMonitor->hrgnMonitor)
IntGdiSetRegionOwner(pMonitor->hrgnMonitor, GDI_OBJ_HMGR_PUBLIC); IntGdiSetRegionOwner(pMonitor->hrgnMonitor, GDI_OBJ_HMGR_PUBLIC);

View file

@ -56,7 +56,7 @@ IntIntersectWithParents(PWND Child, RECTL *WindowRect)
} }
BOOL FASTCALL BOOL FASTCALL
IntValidateParent(PWND Child, HRGN hValidateRgn, BOOL Recurse) IntValidateParent(PWND Child, PREGION ValidateRgn, BOOL Recurse)
{ {
PWND ParentWnd = Child; PWND ParentWnd = Child;
@ -81,7 +81,7 @@ IntValidateParent(PWND Child, HRGN hValidateRgn, BOOL Recurse)
return FALSE; return FALSE;
IntInvalidateWindows( ParentWnd, IntInvalidateWindows( ParentWnd,
hValidateRgn, ValidateRgn,
RDW_VALIDATE | RDW_NOCHILDREN); RDW_VALIDATE | RDW_NOCHILDREN);
} }
@ -177,9 +177,21 @@ IntCalcWindowRgn(PWND Wnd, BOOL Client)
HRGN hRgnWindow; HRGN hRgnWindow;
if (Client) if (Client)
hRgnWindow = IntSysCreateRectRgnIndirect(&Wnd->rcClient); {
hRgnWindow = NtGdiCreateRectRgn(
Wnd->rcClient.left,
Wnd->rcClient.top,
Wnd->rcClient.right,
Wnd->rcClient.bottom);
}
else else
hRgnWindow = IntSysCreateRectRgnIndirect(&Wnd->rcWindow); {
hRgnWindow = NtGdiCreateRectRgn(
Wnd->rcWindow.left,
Wnd->rcWindow.top,
Wnd->rcWindow.right,
Wnd->rcWindow.bottom);
}
if (Wnd->hrgnClip != NULL && !(Wnd->style & WS_MINIMIZE)) if (Wnd->hrgnClip != NULL && !(Wnd->style & WS_MINIMIZE))
{ {
@ -302,9 +314,17 @@ co_IntPaintWindows(PWND Wnd, ULONG Flags, BOOL Recurse)
{ {
if (Wnd->hrgnUpdate) if (Wnd->hrgnUpdate)
{ {
if (!IntValidateParent(Wnd, Wnd->hrgnUpdate, Recurse)) PREGION RgnUpdate = RGNOBJAPI_Lock(Wnd->hrgnUpdate, NULL);
if (RgnUpdate)
{
if (!IntValidateParent(Wnd, RgnUpdate, Recurse))
{
RGNOBJAPI_Unlock(RgnUpdate);
return; return;
} }
RGNOBJAPI_Unlock(RgnUpdate);
}
}
if (Flags & RDW_UPDATENOW) if (Flags & RDW_UPDATENOW)
{ {
@ -397,7 +417,7 @@ co_IntPaintWindows(PWND Wnd, ULONG Flags, BOOL Recurse)
* co_WinPosSetWindowPos, IntValidateParent, co_UserRedrawWindow. * co_WinPosSetWindowPos, IntValidateParent, co_UserRedrawWindow.
*/ */
VOID FASTCALL VOID FASTCALL
IntInvalidateWindows(PWND Wnd, HRGN hRgn, ULONG Flags) IntInvalidateWindows(PWND Wnd, PREGION Rgn, ULONG Flags)
{ {
INT RgnType; INT RgnType;
BOOL HadPaintMessage; BOOL HadPaintMessage;
@ -412,11 +432,14 @@ IntInvalidateWindows(PWND Wnd, HRGN hRgn, ULONG Flags)
*/ */
if (0 != (Flags & RDW_INVALIDATE) && 0 == (Flags & RDW_FRAME)) if (0 != (Flags & RDW_INVALIDATE) && 0 == (Flags & RDW_FRAME))
{ {
HRGN hRgnClient; PREGION RgnClient;
hRgnClient = IntSysCreateRectRgnIndirect(&Wnd->rcClient); RgnClient = IntSysCreateRectpRgnIndirect(&Wnd->rcClient);
RgnType = NtGdiCombineRgn(hRgn, hRgn, hRgnClient, RGN_AND); if (RgnClient)
GreDeleteObject(hRgnClient); {
RgnType = IntGdiCombineRgn(Rgn, Rgn, RgnClient, RGN_AND);
REGION_Delete(RgnClient);
}
} }
/* /*
@ -425,21 +448,27 @@ IntInvalidateWindows(PWND Wnd, HRGN hRgn, ULONG Flags)
if (!Wnd->hrgnClip || (Wnd->style & WS_MINIMIZE)) if (!Wnd->hrgnClip || (Wnd->style & WS_MINIMIZE))
{ {
HRGN hRgnWindow; PREGION RgnWindow = IntSysCreateRectpRgnIndirect(&Wnd->rcWindow);
if (RgnWindow)
hRgnWindow = IntSysCreateRectRgnIndirect(&Wnd->rcWindow); {
RgnType = NtGdiCombineRgn(hRgn, hRgn, hRgnWindow, RGN_AND); RgnType = IntGdiCombineRgn(Rgn, Rgn, RgnWindow, RGN_AND);
GreDeleteObject(hRgnWindow); REGION_Delete(RgnWindow);
}
} }
else else
{ {
NtGdiOffsetRgn( hRgn, PREGION RgnClip = RGNOBJAPI_Lock(Wnd->hrgnClip, NULL);
if (RgnClip)
{
IntGdiOffsetRgn( Rgn,
-Wnd->rcWindow.left, -Wnd->rcWindow.left,
-Wnd->rcWindow.top); -Wnd->rcWindow.top);
RgnType = NtGdiCombineRgn(hRgn, hRgn, Wnd->hrgnClip, RGN_AND); RgnType = IntGdiCombineRgn(Rgn, Rgn, RgnClip, RGN_AND);
NtGdiOffsetRgn( hRgn, IntGdiOffsetRgn( Rgn,
Wnd->rcWindow.left, Wnd->rcWindow.left,
Wnd->rcWindow.top); Wnd->rcWindow.top);
RGNOBJAPI_Unlock(RgnClip);
}
} }
/* /*
@ -462,6 +491,8 @@ IntInvalidateWindows(PWND Wnd, HRGN hRgn, ULONG Flags)
if (Flags & RDW_INVALIDATE && RgnType != NULLREGION) if (Flags & RDW_INVALIDATE && RgnType != NULLREGION)
{ {
PREGION RgnUpdate;
Wnd->state &= ~WNDS_NONCPAINT; Wnd->state &= ~WNDS_NONCPAINT;
/* If not the same thread set it dirty. */ /* If not the same thread set it dirty. */
@ -479,17 +510,22 @@ IntInvalidateWindows(PWND Wnd, HRGN hRgn, ULONG Flags)
if (Wnd->hrgnUpdate == NULL) if (Wnd->hrgnUpdate == NULL)
{ {
Wnd->hrgnUpdate = IntSysCreateRectRgn(0, 0, 0, 0); Wnd->hrgnUpdate = NtGdiCreateRectRgn(0, 0, 0, 0);
IntGdiSetRegionOwner(Wnd->hrgnUpdate, GDI_OBJ_HMGR_PUBLIC); IntGdiSetRegionOwner(Wnd->hrgnUpdate, GDI_OBJ_HMGR_PUBLIC);
} }
if (NtGdiCombineRgn(Wnd->hrgnUpdate, Wnd->hrgnUpdate, RgnUpdate = RGNOBJAPI_Lock(Wnd->hrgnUpdate, NULL);
hRgn, RGN_OR) == NULLREGION) if (RgnUpdate)
{
RgnType = IntGdiCombineRgn(RgnUpdate, RgnUpdate, Rgn, RGN_OR);
RGNOBJAPI_Unlock(RgnUpdate);
if (RgnType == NULLREGION)
{ {
IntGdiSetRegionOwner(Wnd->hrgnUpdate, GDI_OBJ_HMGR_POWNED); IntGdiSetRegionOwner(Wnd->hrgnUpdate, GDI_OBJ_HMGR_POWNED);
GreDeleteObject(Wnd->hrgnUpdate); GreDeleteObject(Wnd->hrgnUpdate);
Wnd->hrgnUpdate = NULL; Wnd->hrgnUpdate = NULL;
} }
}
Flags |= RDW_FRAME; // For children. Flags |= RDW_FRAME; // For children.
} }
} // The following flags are used to validate the window. } // The following flags are used to validate the window.
@ -511,14 +547,21 @@ IntInvalidateWindows(PWND Wnd, HRGN hRgn, ULONG Flags)
if (Wnd->hrgnUpdate != NULL) if (Wnd->hrgnUpdate != NULL)
{ {
if (NtGdiCombineRgn(Wnd->hrgnUpdate, Wnd->hrgnUpdate, PREGION RgnUpdate = RGNOBJAPI_Lock(Wnd->hrgnUpdate, NULL);
hRgn, RGN_DIFF) == NULLREGION)
if (RgnUpdate)
{
RgnType = IntGdiCombineRgn(RgnUpdate, RgnUpdate, Rgn, RGN_DIFF);
RGNOBJAPI_Unlock(RgnUpdate);
if(RgnType == NULLREGION)
{ {
IntGdiSetRegionOwner(Wnd->hrgnUpdate, GDI_OBJ_HMGR_POWNED); IntGdiSetRegionOwner(Wnd->hrgnUpdate, GDI_OBJ_HMGR_POWNED);
GreDeleteObject(Wnd->hrgnUpdate); GreDeleteObject(Wnd->hrgnUpdate);
Wnd->hrgnUpdate = NULL; Wnd->hrgnUpdate = NULL;
} }
} }
}
if (Wnd->hrgnUpdate == NULL) if (Wnd->hrgnUpdate == NULL)
Wnd->state &= ~(WNDS_SENDERASEBACKGROUND|WNDS_ERASEBACKGROUND); Wnd->state &= ~(WNDS_SENDERASEBACKGROUND|WNDS_ERASEBACKGROUND);
@ -541,10 +584,13 @@ IntInvalidateWindows(PWND Wnd, HRGN hRgn, ULONG Flags)
/* /*
* Recursive call to update children hrgnUpdate * Recursive call to update children hrgnUpdate
*/ */
HRGN hRgnTemp = IntSysCreateRectRgn(0, 0, 0, 0); PREGION RgnTemp = IntSysCreateRectpRgn(0, 0, 0, 0);
NtGdiCombineRgn(hRgnTemp, hRgn, 0, RGN_COPY); if (RgnTemp)
IntInvalidateWindows(Child, hRgnTemp, Flags); {
GreDeleteObject(hRgnTemp); IntGdiCombineRgn(RgnTemp, Rgn, 0, RGN_COPY);
IntInvalidateWindows(Child, RgnTemp, Flags);
REGION_Delete(RgnTemp);
}
} }
} }
} }
@ -602,10 +648,10 @@ BOOL FASTCALL
co_UserRedrawWindow( co_UserRedrawWindow(
PWND Window, PWND Window,
const RECTL* UpdateRect, const RECTL* UpdateRect,
HRGN UpdateRgn, PREGION UpdateRgn,
ULONG Flags) ULONG Flags)
{ {
HRGN hRgn = NULL; PREGION TmpRgn = NULL;
TRACE("co_UserRedrawWindow start\n"); TRACE("co_UserRedrawWindow start\n");
/* /*
@ -626,35 +672,37 @@ co_UserRedrawWindow(
if (Flags & (RDW_INVALIDATE | RDW_VALIDATE)) // Both are OKAY! if (Flags & (RDW_INVALIDATE | RDW_VALIDATE)) // Both are OKAY!
{ {
if (UpdateRgn != NULL) if (UpdateRgn)
{ {
hRgn = IntSysCreateRectRgn(0, 0, 0, 0); TmpRgn = IntSysCreateRectpRgn(0, 0, 0, 0);
if (NtGdiCombineRgn(hRgn, UpdateRgn, NULL, RGN_COPY) == NULLREGION) if (IntGdiCombineRgn(TmpRgn, UpdateRgn, NULL, RGN_COPY) == NULLREGION)
{ {
GreDeleteObject(hRgn); REGION_Delete(TmpRgn);
hRgn = NULL; TmpRgn = NULL;
} }
else else
NtGdiOffsetRgn(hRgn, Window->rcClient.left, Window->rcClient.top); {
IntGdiOffsetRgn(TmpRgn, Window->rcClient.left, Window->rcClient.top);
}
} }
else if (UpdateRect != NULL) else if (UpdateRect != NULL)
{ {
if (!RECTL_bIsEmptyRect(UpdateRect)) if (!RECTL_bIsEmptyRect(UpdateRect))
{ {
hRgn = IntSysCreateRectRgnIndirect((RECTL *)UpdateRect); TmpRgn = IntSysCreateRectpRgnIndirect(UpdateRect);
NtGdiOffsetRgn(hRgn, Window->rcClient.left, Window->rcClient.top); IntGdiOffsetRgn(TmpRgn, Window->rcClient.left, Window->rcClient.top);
} }
} }
else if ((Flags & (RDW_INVALIDATE | RDW_FRAME)) == (RDW_INVALIDATE | RDW_FRAME) || else if ((Flags & (RDW_INVALIDATE | RDW_FRAME)) == (RDW_INVALIDATE | RDW_FRAME) ||
(Flags & (RDW_VALIDATE | RDW_NOFRAME)) == (RDW_VALIDATE | RDW_NOFRAME)) (Flags & (RDW_VALIDATE | RDW_NOFRAME)) == (RDW_VALIDATE | RDW_NOFRAME))
{ {
if (!RECTL_bIsEmptyRect(&Window->rcWindow)) if (!RECTL_bIsEmptyRect(&Window->rcWindow))
hRgn = IntSysCreateRectRgnIndirect(&Window->rcWindow); TmpRgn = IntSysCreateRectpRgnIndirect(&Window->rcWindow);
} }
else else
{ {
if (!RECTL_bIsEmptyRect(&Window->rcClient)) if (!RECTL_bIsEmptyRect(&Window->rcClient))
hRgn = IntSysCreateRectRgnIndirect(&Window->rcClient); TmpRgn = IntSysCreateRectpRgnIndirect(&Window->rcClient);
} }
} }
@ -664,9 +712,9 @@ co_UserRedrawWindow(
*/ */
if (Flags & (RDW_INVALIDATE | RDW_VALIDATE | RDW_INTERNALPAINT | RDW_NOINTERNALPAINT) && if (Flags & (RDW_INVALIDATE | RDW_VALIDATE | RDW_INTERNALPAINT | RDW_NOINTERNALPAINT) &&
hRgn != NULL) TmpRgn != NULL)
{ {
IntInvalidateWindows(Window, hRgn, Flags); IntInvalidateWindows(Window, TmpRgn, Flags);
} }
/* /*
@ -685,9 +733,9 @@ co_UserRedrawWindow(
* Cleanup ;-) * Cleanup ;-)
*/ */
if (hRgn != NULL) if (TmpRgn != NULL)
{ {
GreDeleteObject(hRgn); REGION_Delete(TmpRgn);
} }
TRACE("co_UserRedrawWindow exit\n"); TRACE("co_UserRedrawWindow exit\n");
@ -991,7 +1039,7 @@ IntBeginPaint(PWND Window, PPAINTSTRUCT Ps)
for (Child = Window->spwndChild; Child; Child = Child->spwndNext) for (Child = Window->spwndChild; Child; Child = Child->spwndNext)
{ {
if (Child->hrgnUpdate == NULL && Child->state & WNDS_SENDNCPAINT) // Helped fixing test_redrawnow. if (Child->hrgnUpdate == NULL && Child->state & WNDS_SENDNCPAINT) // Helped fixing test_redrawnow.
IntInvalidateWindows(Child, Window->hrgnUpdate, RDW_FRAME | RDW_ERASE | RDW_INVALIDATE | RDW_ALLCHILDREN); IntInvalidateWindows(Child, NULL, RDW_FRAME | RDW_ERASE | RDW_INVALIDATE | RDW_ALLCHILDREN);
} }
} }
} }
@ -1157,10 +1205,11 @@ Exit:
} }
INT FASTCALL INT FASTCALL
co_UserGetUpdateRgn(PWND Window, HRGN hRgn, BOOL bErase) co_UserGetUpdateRgn(PWND Window, PREGION Rgn, BOOL bErase)
{ {
int RegionType; int RegionType;
RECTL Rect; RECTL Rect;
PREGION UpdateRgn;
ASSERT_REFS_CO(Window); ASSERT_REFS_CO(Window);
@ -1168,22 +1217,27 @@ co_UserGetUpdateRgn(PWND Window, HRGN hRgn, BOOL bErase)
if (Window->hrgnUpdate == NULL) if (Window->hrgnUpdate == NULL)
{ {
RegionType = (NtGdiSetRectRgn(hRgn, 0, 0, 0, 0) ? NULLREGION : ERROR); REGION_SetRectRgn(Rgn, 0, 0, 0, 0);
return NULLREGION;
} }
else
{ UpdateRgn = RGNOBJAPI_Lock(Window->hrgnUpdate, NULL);
if (!UpdateRgn)
return ERROR;
Rect = Window->rcClient; Rect = Window->rcClient;
IntIntersectWithParents(Window, &Rect); IntIntersectWithParents(Window, &Rect);
NtGdiSetRectRgn(hRgn, Rect.left, Rect.top, Rect.right, Rect.bottom); REGION_SetRectRgn(Rgn, Rect.left, Rect.top, Rect.right, Rect.bottom);
RegionType = NtGdiCombineRgn(hRgn, hRgn, Window->hrgnUpdate, RGN_AND); RegionType = IntGdiCombineRgn(Rgn, Rgn, UpdateRgn, RGN_AND);
NtGdiOffsetRgn(hRgn, -Window->rcClient.left, -Window->rcClient.top); IntGdiOffsetRgn(Rgn, -Window->rcClient.left, -Window->rcClient.top);
}
if (bErase && RegionType != NULLREGION && RegionType != ERROR) if (bErase && RegionType != NULLREGION && RegionType != ERROR)
{ {
co_UserRedrawWindow(Window, NULL, NULL, RDW_ERASENOW | RDW_NOCHILDREN); co_UserRedrawWindow(Window, NULL, NULL, RDW_ERASENOW | RDW_NOCHILDREN);
} }
RGNOBJAPI_Unlock(UpdateRgn);
return RegionType; return RegionType;
} }
@ -1201,6 +1255,7 @@ NtUserGetUpdateRgn(HWND hWnd, HRGN hRgn, BOOL bErase)
PWND Window; PWND Window;
INT ret; INT ret;
USER_REFERENCE_ENTRY Ref; USER_REFERENCE_ENTRY Ref;
PREGION Rgn = NULL;
TRACE("Enter NtUserGetUpdateRgn\n"); TRACE("Enter NtUserGetUpdateRgn\n");
UserEnterExclusive(); UserEnterExclusive();
@ -1210,13 +1265,19 @@ NtUserGetUpdateRgn(HWND hWnd, HRGN hRgn, BOOL bErase)
RETURN(ERROR); RETURN(ERROR);
} }
Rgn = RGNOBJAPI_Lock(hRgn, NULL);
if (!Rgn)
RETURN(ERROR);
UserRefObjectCo(Window, &Ref); UserRefObjectCo(Window, &Ref);
ret = co_UserGetUpdateRgn(Window, hRgn, bErase); ret = co_UserGetUpdateRgn(Window, Rgn, bErase);
UserDerefObjectCo(Window); UserDerefObjectCo(Window);
RETURN(ret); RETURN(ret);
CLEANUP: CLEANUP:
if (Rgn)
RGNOBJAPI_Unlock(Rgn);
TRACE("Leave NtUserGetUpdateRgn, ret=%i\n",_ret_); TRACE("Leave NtUserGetUpdateRgn, ret=%i\n",_ret_);
UserLeave(); UserLeave();
END_CLEANUP; END_CLEANUP;
@ -1327,6 +1388,7 @@ NtUserRedrawWindow(
BOOL Ret; BOOL Ret;
USER_REFERENCE_ENTRY Ref; USER_REFERENCE_ENTRY Ref;
NTSTATUS Status = STATUS_SUCCESS; NTSTATUS Status = STATUS_SUCCESS;
PREGION RgnUpdate = NULL;
DECLARE_RETURN(BOOL); DECLARE_RETURN(BOOL);
TRACE("Enter NtUserRedrawWindow\n"); TRACE("Enter NtUserRedrawWindow\n");
@ -1365,11 +1427,21 @@ NtUserRedrawWindow(
RETURN( FALSE); RETURN( FALSE);
} }
if (hrgnUpdate)
{
RgnUpdate = RGNOBJAPI_Lock(hrgnUpdate, NULL);
if (!RgnUpdate)
{
EngSetLastError(ERROR_INVALID_HANDLE);
RETURN(FALSE);
}
}
UserRefObjectCo(Wnd, &Ref); UserRefObjectCo(Wnd, &Ref);
Ret = co_UserRedrawWindow( Wnd, Ret = co_UserRedrawWindow( Wnd,
lprcUpdate ? &SafeUpdateRect : NULL, lprcUpdate ? &SafeUpdateRect : NULL,
hrgnUpdate, RgnUpdate,
flags); flags);
UserDerefObjectCo(Wnd); UserDerefObjectCo(Wnd);
@ -1377,6 +1449,8 @@ NtUserRedrawWindow(
RETURN( Ret); RETURN( Ret);
CLEANUP: CLEANUP:
if (RgnUpdate)
RGNOBJAPI_Unlock(RgnUpdate);
TRACE("Leave NtUserRedrawWindow, ret=%i\n",_ret_); TRACE("Leave NtUserRedrawWindow, ret=%i\n",_ret_);
UserLeave(); UserLeave();
END_CLEANUP; END_CLEANUP;
@ -1390,7 +1464,7 @@ UserScrollDC(
INT dy, INT dy,
const RECTL *prcScroll, const RECTL *prcScroll,
const RECTL *prcClip, const RECTL *prcClip,
HRGN hrgnUpdate, PREGION RgnUpdate,
RECTL *prcUpdate) RECTL *prcUpdate)
{ {
PDC pDC; PDC pDC;
@ -1435,10 +1509,9 @@ UserScrollDC(
/* Calculate the region that was invalidated by moving or /* Calculate the region that was invalidated by moving or
could not be copied, because it was not visible */ could not be copied, because it was not visible */
if (hrgnUpdate || prcUpdate) if (RgnUpdate || prcUpdate)
{ {
HRGN hrgnOwn, hrgnTmp; PREGION RgnOwn, RgnTmp;
PREGION prgnTmp;
pDC = DC_LockDc(hDC); pDC = DC_LockDc(hDC);
if (!pDC) if (!pDC)
@ -1450,44 +1523,38 @@ UserScrollDC(
rcDst = rcScroll; rcDst = rcScroll;
RECTL_vOffsetRect(&rcDst, dx, dy); RECTL_vOffsetRect(&rcDst, dx, dy);
RECTL_bIntersectRect(&rcDst, &rcDst, &rcClip); RECTL_bIntersectRect(&rcDst, &rcDst, &rcClip);
if (hrgnUpdate) if (RgnUpdate)
{ {
hrgnOwn = hrgnUpdate; RgnOwn = RgnUpdate;
if (!NtGdiSetRectRgn(hrgnOwn, rcDst.left, rcDst.top, rcDst.right, rcDst.bottom)) REGION_SetRectRgn(RgnOwn, rcDst.left, rcDst.top, rcDst.right, rcDst.bottom);
{
DC_UnlockDc(pDC);
return ERROR;
}
} }
else else
{ {
hrgnOwn = IntSysCreateRectRgnIndirect(&rcDst); RgnOwn = IntSysCreateRectpRgnIndirect(&rcDst);
} }
/* Add the source rect */ /* Add the source rect */
hrgnTmp = IntSysCreateRectRgnIndirect(&rcSrc); RgnTmp = IntSysCreateRectpRgnIndirect(&rcSrc);
NtGdiCombineRgn(hrgnOwn, hrgnOwn, hrgnTmp, RGN_OR); IntGdiCombineRgn(RgnOwn, RgnOwn, RgnTmp, RGN_OR);
/* Substract the part of the dest that was visible in source */ /* Substract the part of the dest that was visible in source */
prgnTmp = RGNOBJAPI_Lock(hrgnTmp, NULL); IntGdiCombineRgn(RgnTmp, RgnTmp, pDC->prgnVis, RGN_AND);
IntGdiCombineRgn(prgnTmp, prgnTmp, pDC->prgnVis, RGN_AND); IntGdiOffsetRgn(RgnTmp, dx, dy);
RGNOBJAPI_Unlock(prgnTmp); Result = IntGdiCombineRgn(RgnOwn, RgnOwn, RgnTmp, RGN_DIFF);
NtGdiOffsetRgn(hrgnTmp, dx, dy);
Result = NtGdiCombineRgn(hrgnOwn, hrgnOwn, hrgnTmp, RGN_DIFF);
/* DO NOT Unlock DC while messing with prgnVis! */ /* DO NOT Unlock DC while messing with prgnVis! */
DC_UnlockDc(pDC); DC_UnlockDc(pDC);
GreDeleteObject(hrgnTmp); REGION_Delete(RgnTmp);
if (prcUpdate) if (prcUpdate)
{ {
IntGdiGetRgnBox(hrgnOwn, prcUpdate); REGION_GetRgnBox(RgnOwn, prcUpdate);
} }
if (!hrgnUpdate) if (!RgnUpdate)
{ {
GreDeleteObject(hrgnOwn); REGION_Delete(RgnOwn);
} }
} }
else else
@ -1516,6 +1583,7 @@ NtUserScrollDC(
RECTL rcScroll, rcClip, rcUpdate; RECTL rcScroll, rcClip, rcUpdate;
NTSTATUS Status = STATUS_SUCCESS; NTSTATUS Status = STATUS_SUCCESS;
DWORD Result; DWORD Result;
PREGION RgnUpdate = NULL;
TRACE("Enter NtUserScrollDC\n"); TRACE("Enter NtUserScrollDC\n");
UserEnterExclusive(); UserEnterExclusive();
@ -1548,12 +1616,19 @@ NtUserScrollDC(
RETURN(FALSE); RETURN(FALSE);
} }
if (hrgnUpdate)
{
RgnUpdate = RGNOBJAPI_Lock(hrgnUpdate, NULL);
if (!RgnUpdate)
RETURN(FALSE);
}
Result = UserScrollDC( hDC, Result = UserScrollDC( hDC,
dx, dx,
dy, dy,
prcUnsafeScroll? &rcScroll : 0, prcUnsafeScroll? &rcScroll : 0,
prcUnsafeClip? &rcClip : 0, prcUnsafeClip? &rcClip : 0,
hrgnUpdate, RgnUpdate,
prcUnsafeUpdate? &rcUpdate : NULL); prcUnsafeUpdate? &rcUpdate : NULL);
if(Result == ERROR) if(Result == ERROR)
{ {
@ -1583,6 +1658,8 @@ NtUserScrollDC(
RETURN(TRUE); RETURN(TRUE);
CLEANUP: CLEANUP:
if (RgnUpdate)
RGNOBJAPI_Unlock(RgnUpdate);
TRACE("Leave NtUserScrollDC, ret=%lu\n",_ret_); TRACE("Leave NtUserScrollDC, ret=%lu\n",_ret_);
UserLeave(); UserLeave();
END_CLEANUP; END_CLEANUP;
@ -1610,7 +1687,7 @@ NtUserScrollWindowEx(
INT Result; INT Result;
PWND Window = NULL, CaretWnd; PWND Window = NULL, CaretWnd;
HDC hDC; HDC hDC;
HRGN hrgnOwn = NULL, hrgnTemp, hrgnWinupd = NULL; PREGION RgnOwn = NULL, RgnTemp, RgnWinupd = NULL;
HWND hwndCaret; HWND hwndCaret;
DWORD dcxflags = 0; DWORD dcxflags = 0;
int rdw_flags; int rdw_flags;
@ -1668,11 +1745,15 @@ NtUserScrollWindowEx(
if (hrgnUpdate) if (hrgnUpdate)
{ {
hrgnOwn = hrgnUpdate; RgnOwn = RGNOBJAPI_Lock(hrgnUpdate, NULL);
if (!RgnOwn)
{
RETURN(ERROR);
}
bOwnRgn = FALSE; bOwnRgn = FALSE;
} }
else else
hrgnOwn = IntSysCreateRectRgn(0, 0, 0, 0); RgnOwn = IntSysCreateRectpRgn(0, 0, 0, 0);
/* ScrollWindow uses the window DC, ScrollWindowEx doesn't */ /* ScrollWindow uses the window DC, ScrollWindowEx doesn't */
if (flags & SW_SCROLLWNDDCE) if (flags & SW_SCROLLWNDDCE)
@ -1709,7 +1790,7 @@ NtUserScrollWindowEx(
dy, dy,
&rcScroll, &rcScroll,
&rcClip, &rcClip,
hrgnOwn, RgnOwn,
prcUnsafeUpdate? &rcUpdate : NULL); prcUnsafeUpdate? &rcUpdate : NULL);
UserReleaseDC(Window, hDC, FALSE); UserReleaseDC(Window, hDC, FALSE);
@ -1719,22 +1800,29 @@ NtUserScrollWindowEx(
* the scroll. Keep a copy in hrgnWinupd to be added to hrngUpdate at the end. * the scroll. Keep a copy in hrgnWinupd to be added to hrngUpdate at the end.
*/ */
hrgnTemp = IntSysCreateRectRgn(0, 0, 0, 0); RgnTemp = IntSysCreateRectpRgn(0, 0, 0, 0);
if (co_UserGetUpdateRgn(Window, hrgnTemp, FALSE) != NULLREGION) if (RgnTemp)
{
if (co_UserGetUpdateRgn(Window, RgnTemp, FALSE) != NULLREGION)
{
PREGION RgnClip = IntSysCreateRectpRgnIndirect(&rcClip);
if (RgnClip)
{ {
HRGN hrgnClip = IntSysCreateRectRgnIndirect(&rcClip);
if (!bOwnRgn) if (!bOwnRgn)
{ {
hrgnWinupd = IntSysCreateRectRgn( 0, 0, 0, 0); RgnWinupd = IntSysCreateRectpRgn( 0, 0, 0, 0);
NtGdiCombineRgn( hrgnWinupd, hrgnTemp, 0, RGN_COPY); IntGdiCombineRgn( RgnWinupd, RgnTemp, 0, RGN_COPY);
} }
NtGdiOffsetRgn(hrgnTemp, dx, dy); IntGdiOffsetRgn(RgnTemp, dx, dy);
NtGdiCombineRgn(hrgnTemp, hrgnTemp, hrgnClip, RGN_AND); IntGdiCombineRgn(RgnTemp, RgnTemp, RgnClip, RGN_AND);
if (!bOwnRgn) NtGdiCombineRgn( hrgnWinupd, hrgnWinupd, hrgnTemp, RGN_OR ); if (!bOwnRgn)
co_UserRedrawWindow(Window, NULL, hrgnTemp, rdw_flags ); IntGdiCombineRgn( RgnWinupd, RgnWinupd, RgnTemp, RGN_OR );
GreDeleteObject(hrgnClip); co_UserRedrawWindow(Window, NULL, RgnTemp, rdw_flags );
REGION_Delete(RgnClip);
}
}
REGION_Delete(RgnTemp);
} }
GreDeleteObject(hrgnTemp);
if (flags & SW_SCROLLCHILDREN) if (flags & SW_SCROLLCHILDREN)
{ {
@ -1766,7 +1854,7 @@ NtUserScrollWindowEx(
if (flags & (SW_INVALIDATE | SW_ERASE)) if (flags & (SW_INVALIDATE | SW_ERASE))
{ {
co_UserRedrawWindow(Window, NULL, hrgnOwn, rdw_flags | co_UserRedrawWindow(Window, NULL, RgnOwn, rdw_flags |
((flags & SW_ERASE) ? RDW_ERASENOW : 0) | ((flags & SW_ERASE) ? RDW_ERASENOW : 0) |
((flags & SW_SCROLLCHILDREN) ? RDW_ALLCHILDREN : 0)); ((flags & SW_SCROLLCHILDREN) ? RDW_ALLCHILDREN : 0));
} }
@ -1805,15 +1893,19 @@ NtUserScrollWindowEx(
RETURN(Result); RETURN(Result);
CLEANUP: CLEANUP:
if (hrgnWinupd && !bOwnRgn) if (RgnWinupd && !bOwnRgn)
{ {
NtGdiCombineRgn( hrgnOwn, hrgnOwn, hrgnWinupd, RGN_OR); IntGdiCombineRgn( RgnOwn, RgnOwn, RgnWinupd, RGN_OR);
GreDeleteObject(hrgnWinupd); REGION_Delete(RgnWinupd);
} }
if (hrgnOwn && !hrgnUpdate) if (RgnOwn && !hrgnUpdate)
{ {
GreDeleteObject(hrgnOwn); REGION_Delete(RgnOwn);
}
else if (RgnOwn)
{
RGNOBJAPI_Unlock(RgnOwn);
} }
if (Window) if (Window)

View file

@ -1,12 +1,12 @@
#pragma once #pragma once
BOOL FASTCALL co_UserRedrawWindow(PWND Wnd, const RECTL* UpdateRect, HRGN UpdateRgn, ULONG Flags); BOOL FASTCALL co_UserRedrawWindow(PWND Wnd, const RECTL* UpdateRect, PREGION UpdateRgn, ULONG Flags);
VOID FASTCALL IntInvalidateWindows(PWND Window, HRGN hRgn, ULONG Flags); VOID FASTCALL IntInvalidateWindows(PWND Window, PREGION Rgn, ULONG Flags);
BOOL FASTCALL IntGetPaintMessage(PWND Window, UINT MsgFilterMin, UINT MsgFilterMax, PTHREADINFO Thread, MSG *Message, BOOL Remove); BOOL FASTCALL IntGetPaintMessage(PWND Window, UINT MsgFilterMin, UINT MsgFilterMax, PTHREADINFO Thread, MSG *Message, BOOL Remove);
INT FASTCALL UserRealizePalette(HDC); INT FASTCALL UserRealizePalette(HDC);
INT FASTCALL co_UserGetUpdateRgn(PWND, HRGN, BOOL); INT FASTCALL co_UserGetUpdateRgn(PWND, PREGION, BOOL);
VOID FASTCALL co_IntPaintWindows(PWND Window, ULONG Flags, BOOL Recurse); VOID FASTCALL co_IntPaintWindows(PWND Window, ULONG Flags, BOOL Recurse);
BOOL FASTCALL IntValidateParent(PWND Child, HRGN hValidateRgn, BOOL Recurse); BOOL FASTCALL IntValidateParent(PWND Child, PREGION ValidateRgn, BOOL Recurse);
BOOL FASTCALL IntIsWindowDirty(PWND); BOOL FASTCALL IntIsWindowDirty(PWND);
BOOL FASTCALL IntEndPaint(PWND,PPAINTSTRUCT); BOOL FASTCALL IntEndPaint(PWND,PPAINTSTRUCT);
HDC FASTCALL IntBeginPaint(PWND,PPAINTSTRUCT); HDC FASTCALL IntBeginPaint(PWND,PPAINTSTRUCT);

View file

@ -793,9 +793,16 @@ NtUserCallHwndParamLock(
switch (Routine) switch (Routine)
{ {
case TWOPARAM_ROUTINE_VALIDATERGN: case TWOPARAM_ROUTINE_VALIDATERGN:
Ret = (DWORD)co_UserRedrawWindow( Window, NULL, (HRGN)Param, RDW_VALIDATE); {
PREGION Rgn = RGNOBJAPI_Lock((HRGN)Param, NULL);
if (Rgn)
{
Ret = (DWORD)co_UserRedrawWindow( Window, NULL, Rgn, RDW_VALIDATE);
RGNOBJAPI_Unlock(Rgn);
}
break; break;
} }
}
UserDerefObjectCo(Window); UserDerefObjectCo(Window);

View file

@ -9,14 +9,14 @@
#include <win32k.h> #include <win32k.h>
DBG_DEFAULT_CHANNEL(UserWinpos); DBG_DEFAULT_CHANNEL(UserWinpos);
HRGN FASTCALL PREGION FASTCALL
VIS_ComputeVisibleRegion( VIS_ComputeVisibleRegion(
PWND Wnd, PWND Wnd,
BOOLEAN ClientArea, BOOLEAN ClientArea,
BOOLEAN ClipChildren, BOOLEAN ClipChildren,
BOOLEAN ClipSiblings) BOOLEAN ClipSiblings)
{ {
HRGN VisRgn, ClipRgn; PREGION VisRgn, ClipRgn;
PWND PreviousWindow, CurrentWindow, CurrentSibling; PWND PreviousWindow, CurrentWindow, CurrentSibling;
if (!Wnd || !(Wnd->style & WS_VISIBLE)) if (!Wnd || !(Wnd->style & WS_VISIBLE))
@ -28,11 +28,11 @@ VIS_ComputeVisibleRegion(
if (ClientArea) if (ClientArea)
{ {
VisRgn = IntSysCreateRectRgnIndirect(&Wnd->rcClient); VisRgn = IntSysCreateRectpRgnIndirect(&Wnd->rcClient);
} }
else else
{ {
VisRgn = IntSysCreateRectRgnIndirect(&Wnd->rcWindow); VisRgn = IntSysCreateRectpRgnIndirect(&Wnd->rcWindow);
} }
/* /*
@ -48,19 +48,21 @@ VIS_ComputeVisibleRegion(
if (!VerifyWnd(CurrentWindow)) if (!VerifyWnd(CurrentWindow))
{ {
ERR("ATM the Current Window or Parent is dead! %p\n",CurrentWindow); ERR("ATM the Current Window or Parent is dead! %p\n",CurrentWindow);
if (VisRgn) GreDeleteObject(VisRgn); if (VisRgn)
REGION_Delete(VisRgn);
return NULL; return NULL;
} }
if (!(CurrentWindow->style & WS_VISIBLE)) if (!(CurrentWindow->style & WS_VISIBLE))
{ {
if (VisRgn) GreDeleteObject(VisRgn); if (VisRgn)
REGION_Delete(VisRgn);
return NULL; return NULL;
} }
ClipRgn = IntSysCreateRectRgnIndirect(&CurrentWindow->rcClient); ClipRgn = IntSysCreateRectpRgnIndirect(&CurrentWindow->rcClient);
NtGdiCombineRgn(VisRgn, VisRgn, ClipRgn, RGN_AND); IntGdiCombineRgn(VisRgn, VisRgn, ClipRgn, RGN_AND);
GreDeleteObject(ClipRgn); REGION_Delete(ClipRgn);
if ((PreviousWindow->style & WS_CLIPSIBLINGS) || if ((PreviousWindow->style & WS_CLIPSIBLINGS) ||
(PreviousWindow == Wnd && ClipSiblings)) (PreviousWindow == Wnd && ClipSiblings))
@ -72,16 +74,21 @@ VIS_ComputeVisibleRegion(
if ((CurrentSibling->style & WS_VISIBLE) && if ((CurrentSibling->style & WS_VISIBLE) &&
!(CurrentSibling->ExStyle & WS_EX_TRANSPARENT)) !(CurrentSibling->ExStyle & WS_EX_TRANSPARENT))
{ {
ClipRgn = IntSysCreateRectRgnIndirect(&CurrentSibling->rcWindow); ClipRgn = IntSysCreateRectpRgnIndirect(&CurrentSibling->rcWindow);
/* Combine it with the window region if available */ /* Combine it with the window region if available */
if (CurrentSibling->hrgnClip && !(CurrentSibling->style & WS_MINIMIZE)) if (CurrentSibling->hrgnClip && !(CurrentSibling->style & WS_MINIMIZE))
{ {
NtGdiOffsetRgn(ClipRgn, -CurrentSibling->rcWindow.left, -CurrentSibling->rcWindow.top); PREGION SiblingClipRgn = RGNOBJAPI_Lock(CurrentSibling->hrgnClip, NULL);
NtGdiCombineRgn(ClipRgn, ClipRgn, CurrentSibling->hrgnClip, RGN_AND); if (SiblingClipRgn)
NtGdiOffsetRgn(ClipRgn, CurrentSibling->rcWindow.left, CurrentSibling->rcWindow.top); {
IntGdiOffsetRgn(ClipRgn, -CurrentSibling->rcWindow.left, -CurrentSibling->rcWindow.top);
IntGdiCombineRgn(ClipRgn, ClipRgn, SiblingClipRgn, RGN_AND);
IntGdiOffsetRgn(ClipRgn, CurrentSibling->rcWindow.left, CurrentSibling->rcWindow.top);
RGNOBJAPI_Unlock(SiblingClipRgn);
} }
NtGdiCombineRgn(VisRgn, VisRgn, ClipRgn, RGN_DIFF); }
GreDeleteObject(ClipRgn); IntGdiCombineRgn(VisRgn, VisRgn, ClipRgn, RGN_DIFF);
REGION_Delete(ClipRgn);
} }
CurrentSibling = CurrentSibling->spwndNext; CurrentSibling = CurrentSibling->spwndNext;
} }
@ -99,16 +106,20 @@ VIS_ComputeVisibleRegion(
if ((CurrentWindow->style & WS_VISIBLE) && if ((CurrentWindow->style & WS_VISIBLE) &&
!(CurrentWindow->ExStyle & WS_EX_TRANSPARENT)) !(CurrentWindow->ExStyle & WS_EX_TRANSPARENT))
{ {
ClipRgn = IntSysCreateRectRgnIndirect(&CurrentWindow->rcWindow); ClipRgn = IntSysCreateRectpRgnIndirect(&CurrentWindow->rcWindow);
/* Combine it with the window region if available */ /* Combine it with the window region if available */
if (CurrentWindow->hrgnClip && !(CurrentWindow->style & WS_MINIMIZE)) if (CurrentWindow->hrgnClip && !(CurrentWindow->style & WS_MINIMIZE))
{ {
NtGdiOffsetRgn(ClipRgn, -CurrentWindow->rcWindow.left, -CurrentWindow->rcWindow.top); PREGION CurrentRgnClip = RGNOBJAPI_Lock(CurrentWindow->hrgnClip, NULL);
NtGdiCombineRgn(ClipRgn, ClipRgn, CurrentWindow->hrgnClip, RGN_AND); if (CurrentRgnClip)
NtGdiOffsetRgn(ClipRgn, CurrentWindow->rcWindow.left, CurrentWindow->rcWindow.top); {
IntGdiOffsetRgn(ClipRgn, -CurrentWindow->rcWindow.left, -CurrentWindow->rcWindow.top);
IntGdiCombineRgn(ClipRgn, ClipRgn, CurrentRgnClip, RGN_AND);
IntGdiOffsetRgn(ClipRgn, CurrentWindow->rcWindow.left, CurrentWindow->rcWindow.top);
} }
NtGdiCombineRgn(VisRgn, VisRgn, ClipRgn, RGN_DIFF); }
GreDeleteObject(ClipRgn); IntGdiCombineRgn(VisRgn, VisRgn, ClipRgn, RGN_DIFF);
REGION_Delete(ClipRgn);
} }
CurrentWindow = CurrentWindow->spwndNext; CurrentWindow = CurrentWindow->spwndNext;
} }
@ -116,9 +127,14 @@ VIS_ComputeVisibleRegion(
if (Wnd->hrgnClip && !(Wnd->style & WS_MINIMIZE)) if (Wnd->hrgnClip && !(Wnd->style & WS_MINIMIZE))
{ {
NtGdiOffsetRgn(VisRgn, -Wnd->rcWindow.left, -Wnd->rcWindow.top); PREGION WndRgnClip = RGNOBJAPI_Lock(Wnd->hrgnClip, NULL);
NtGdiCombineRgn(VisRgn, VisRgn, Wnd->hrgnClip, RGN_AND); if (WndRgnClip)
NtGdiOffsetRgn(VisRgn, Wnd->rcWindow.left, Wnd->rcWindow.top); {
IntGdiOffsetRgn(VisRgn, -Wnd->rcWindow.left, -Wnd->rcWindow.top);
IntGdiCombineRgn(VisRgn, VisRgn, WndRgnClip, RGN_AND);
IntGdiOffsetRgn(VisRgn, Wnd->rcWindow.left, Wnd->rcWindow.top);
RGNOBJAPI_Unlock(WndRgnClip);
}
} }
return VisRgn; return VisRgn;
@ -127,9 +143,8 @@ VIS_ComputeVisibleRegion(
VOID FASTCALL VOID FASTCALL
co_VIS_WindowLayoutChanged( co_VIS_WindowLayoutChanged(
PWND Wnd, PWND Wnd,
HRGN NewlyExposed) PREGION NewlyExposed)
{ {
HRGN Temp;
PWND Parent; PWND Parent;
USER_REFERENCE_ENTRY Ref; USER_REFERENCE_ENTRY Ref;
@ -138,20 +153,23 @@ co_VIS_WindowLayoutChanged(
Parent = Wnd->spwndParent; Parent = Wnd->spwndParent;
if(Parent) if(Parent)
{ {
Temp = IntSysCreateRectRgn(0, 0, 0, 0); PREGION TempRgn = IntSysCreateRectpRgn(0, 0, 0, 0);
NtGdiCombineRgn(Temp, NewlyExposed, NULL, RGN_COPY); if (!TempRgn)
NtGdiOffsetRgn(Temp, return;
IntGdiCombineRgn(TempRgn, NewlyExposed, NULL, RGN_COPY);
IntGdiOffsetRgn(TempRgn,
Wnd->rcWindow.left - Parent->rcClient.left, Wnd->rcWindow.left - Parent->rcClient.left,
Wnd->rcWindow.top - Parent->rcClient.top); Wnd->rcWindow.top - Parent->rcClient.top);
UserRefObjectCo(Parent, &Ref); UserRefObjectCo(Parent, &Ref);
co_UserRedrawWindow(Parent, NULL, Temp, co_UserRedrawWindow(Parent, NULL, TempRgn,
RDW_FRAME | RDW_ERASE | RDW_INVALIDATE | RDW_FRAME | RDW_ERASE | RDW_INVALIDATE |
RDW_ALLCHILDREN); RDW_ALLCHILDREN);
UserDerefObjectCo(Parent); UserDerefObjectCo(Parent);
GreDeleteObject(Temp); REGION_Delete(TempRgn);
} }
} }

View file

@ -9,7 +9,7 @@
#pragma once #pragma once
HRGN FASTCALL VIS_ComputeVisibleRegion(PWND Window, BOOLEAN ClientArea, BOOLEAN ClipChildren, BOOLEAN ClipSiblings); PREGION FASTCALL VIS_ComputeVisibleRegion(PWND Window, BOOLEAN ClientArea, BOOLEAN ClipChildren, BOOLEAN ClipSiblings);
VOID FASTCALL co_VIS_WindowLayoutChanged(PWND Window, HRGN UncoveredRgn); VOID FASTCALL co_VIS_WindowLayoutChanged(PWND Window, PREGION UncoveredRgn);
/* EOF */ /* EOF */

View file

@ -69,24 +69,10 @@ static
PREGION FASTCALL PREGION FASTCALL
DceGetVisRgn(PWND Window, ULONG Flags, HWND hWndChild, ULONG CFlags) DceGetVisRgn(PWND Window, ULONG Flags, HWND hWndChild, ULONG CFlags)
{ {
PREGION RetRgn; return VIS_ComputeVisibleRegion( Window,
HRGN hVisRgn;
hVisRgn = VIS_ComputeVisibleRegion( Window,
0 == (Flags & DCX_WINDOW), 0 == (Flags & DCX_WINDOW),
0 != (Flags & DCX_CLIPCHILDREN), 0 != (Flags & DCX_CLIPCHILDREN),
0 != (Flags & DCX_CLIPSIBLINGS)); 0 != (Flags & DCX_CLIPSIBLINGS));
RetRgn = IntSysCreateRectpRgn(0, 0, 0, 0);
if (hVisRgn != NULL)
{
PREGION VisRgn = REGION_LockRgn(hVisRgn);
IntGdiCombineRgn(RetRgn, VisRgn, NULL, RGN_COPY);
REGION_UnlockRgn(VisRgn);
GreDeleteObject(hVisRgn);
}
return RetRgn;
} }
PDCE FASTCALL PDCE FASTCALL
@ -582,11 +568,19 @@ UserGetDCEx(PWND Wnd OPTIONAL, HANDLE ClipRegion, ULONG Flags)
{ {
if (!(Flags & DCX_WINDOW)) if (!(Flags & DCX_WINDOW))
{ {
Dce->hrgnClip = IntSysCreateRectRgnIndirect(&Wnd->rcClient); Dce->hrgnClip = NtGdiCreateRectRgn(
Wnd->rcClient.left,
Wnd->rcClient.top,
Wnd->rcClient.right,
Wnd->rcClient.bottom);
} }
else else
{ {
Dce->hrgnClip = IntSysCreateRectRgnIndirect(&Wnd->rcWindow); Dce->hrgnClip = NtGdiCreateRectRgn(
Wnd->rcWindow.left,
Wnd->rcWindow.top,
Wnd->rcWindow.right,
Wnd->rcWindow.bottom);
} }
Dce->DCXFlags &= ~DCX_KEEPCLIPRGN; Dce->DCXFlags &= ~DCX_KEEPCLIPRGN;
bUpdateVisRgn = TRUE; bUpdateVisRgn = TRUE;

View file

@ -1652,13 +1652,10 @@ co_WinPosSetWindowPos(
RECTL NewWindowRect; RECTL NewWindowRect;
RECTL NewClientRect; RECTL NewClientRect;
RECTL valid_rects[2]; RECTL valid_rects[2];
PROSRGNDATA VisRgn; PREGION VisBefore = NULL;
HRGN VisBefore = NULL; PREGION VisBeforeJustClient = NULL;
HRGN VisBeforeJustClient = NULL; PREGION VisAfter = NULL;
HRGN VisAfter = NULL; PREGION CopyRgn = NULL;
HRGN DirtyRgn = NULL;
HRGN ExposedRgn = NULL;
HRGN CopyRgn = NULL;
ULONG WvrFlags = 0; ULONG WvrFlags = 0;
RECTL OldWindowRect, OldClientRect; RECTL OldWindowRect, OldClientRect;
int RgnType; int RgnType;
@ -1736,20 +1733,16 @@ co_WinPosSetWindowPos(
{ {
VisBefore = VIS_ComputeVisibleRegion(Window, FALSE, FALSE, VisBefore = VIS_ComputeVisibleRegion(Window, FALSE, FALSE,
(Window->style & WS_CLIPSIBLINGS) ? TRUE : FALSE); (Window->style & WS_CLIPSIBLINGS) ? TRUE : FALSE);
VisRgn = NULL;
if ( VisBefore != NULL && if ( VisBefore != NULL &&
(VisRgn = (PROSRGNDATA)RGNOBJAPI_Lock(VisBefore, NULL)) && REGION_Complexity(VisBefore) == NULLREGION )
REGION_Complexity(VisRgn) == NULLREGION )
{ {
RGNOBJAPI_Unlock(VisRgn); REGION_Delete(VisBefore);
GreDeleteObject(VisBefore);
VisBefore = NULL; VisBefore = NULL;
} }
else if(VisRgn) else if(VisBefore)
{ {
RGNOBJAPI_Unlock(VisRgn); IntGdiOffsetRgn(VisBefore, -Window->rcWindow.left, -Window->rcWindow.top);
NtGdiOffsetRgn(VisBefore, -Window->rcWindow.left, -Window->rcWindow.top);
} }
/* Calculate the non client area for resizes, as this is used in the copy region */ /* Calculate the non client area for resizes, as this is used in the copy region */
@ -1757,20 +1750,16 @@ co_WinPosSetWindowPos(
{ {
VisBeforeJustClient = VIS_ComputeVisibleRegion(Window, TRUE, FALSE, VisBeforeJustClient = VIS_ComputeVisibleRegion(Window, TRUE, FALSE,
(Window->style & WS_CLIPSIBLINGS) ? TRUE : FALSE); (Window->style & WS_CLIPSIBLINGS) ? TRUE : FALSE);
VisRgn = NULL;
if ( VisBeforeJustClient != NULL && if ( VisBeforeJustClient != NULL &&
(VisRgn = (PROSRGNDATA)RGNOBJAPI_Lock(VisBeforeJustClient, NULL)) && REGION_Complexity(VisBeforeJustClient) == NULLREGION )
REGION_Complexity(VisRgn) == NULLREGION )
{ {
RGNOBJAPI_Unlock(VisRgn); REGION_Delete(VisBeforeJustClient);
GreDeleteObject(VisBeforeJustClient);
VisBeforeJustClient = NULL; VisBeforeJustClient = NULL;
} }
else if(VisRgn) else if(VisBeforeJustClient)
{ {
RGNOBJAPI_Unlock(VisRgn); IntGdiOffsetRgn(VisBeforeJustClient, -Window->rcWindow.left, -Window->rcWindow.top);
NtGdiOffsetRgn(VisBeforeJustClient, -Window->rcWindow.left, -Window->rcWindow.top);
} }
} }
} }
@ -1843,20 +1832,16 @@ co_WinPosSetWindowPos(
/* Determine the new visible region */ /* Determine the new visible region */
VisAfter = VIS_ComputeVisibleRegion(Window, FALSE, FALSE, VisAfter = VIS_ComputeVisibleRegion(Window, FALSE, FALSE,
(Window->style & WS_CLIPSIBLINGS) ? TRUE : FALSE); (Window->style & WS_CLIPSIBLINGS) ? TRUE : FALSE);
VisRgn = NULL;
if ( VisAfter != NULL && if ( VisAfter != NULL &&
(VisRgn = (PROSRGNDATA)RGNOBJAPI_Lock(VisAfter, NULL)) && REGION_Complexity(VisAfter) == NULLREGION )
REGION_Complexity(VisRgn) == NULLREGION )
{ {
RGNOBJAPI_Unlock(VisRgn); REGION_Delete(VisAfter);
GreDeleteObject(VisAfter);
VisAfter = NULL; VisAfter = NULL;
} }
else if(VisRgn) else if(VisAfter)
{ {
RGNOBJAPI_Unlock(VisRgn); IntGdiOffsetRgn(VisAfter, -Window->rcWindow.left, -Window->rcWindow.top);
NtGdiOffsetRgn(VisAfter, -Window->rcWindow.left, -Window->rcWindow.top);
} }
/* /*
@ -1882,21 +1867,26 @@ co_WinPosSetWindowPos(
* region...) * region...)
*/ */
CopyRgn = IntSysCreateRectRgn(0, 0, 0, 0); CopyRgn = IntSysCreateRectpRgn(0, 0, 0, 0);
if (WinPos.flags & SWP_NOSIZE) if (WinPos.flags & SWP_NOSIZE)
RgnType = NtGdiCombineRgn(CopyRgn, VisAfter, VisBefore, RGN_AND); RgnType = IntGdiCombineRgn(CopyRgn, VisAfter, VisBefore, RGN_AND);
else if (VisBeforeJustClient != NULL) else if (VisBeforeJustClient != NULL)
{ {
RgnType = NtGdiCombineRgn(CopyRgn, VisAfter, VisBeforeJustClient, RGN_AND); RgnType = IntGdiCombineRgn(CopyRgn, VisAfter, VisBeforeJustClient, RGN_AND);
GreDeleteObject(VisBeforeJustClient); REGION_Delete(VisBeforeJustClient);
} }
/* No use in copying bits which are in the update region. */ /* No use in copying bits which are in the update region. */
if (Window->hrgnUpdate != NULL) if (Window->hrgnUpdate != NULL)
{ {
NtGdiOffsetRgn(CopyRgn, NewWindowRect.left, NewWindowRect.top); PREGION RgnUpdate = RGNOBJAPI_Lock(Window->hrgnUpdate, NULL);
NtGdiCombineRgn(CopyRgn, CopyRgn, Window->hrgnUpdate, RGN_DIFF); if (RgnUpdate)
NtGdiOffsetRgn(CopyRgn, -NewWindowRect.left, -NewWindowRect.top); {
IntGdiOffsetRgn(CopyRgn, NewWindowRect.left, NewWindowRect.top);
IntGdiCombineRgn(CopyRgn, CopyRgn, RgnUpdate, RGN_DIFF);
IntGdiOffsetRgn(CopyRgn, -NewWindowRect.left, -NewWindowRect.top);
RGNOBJAPI_Unlock(RgnUpdate);
}
} }
/* /*
@ -1904,21 +1894,17 @@ co_WinPosSetWindowPos(
* 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 ( (VisRgn = (PROSRGNDATA)RGNOBJAPI_Lock(CopyRgn, NULL)) && if (REGION_GetRgnBox(CopyRgn, &CopyRect) == NULLREGION)
REGION_GetRgnBox(VisRgn, &CopyRect) == NULLREGION)
{ {
/* Nothing to copy, clean up */ /* Nothing to copy, clean up */
RGNOBJAPI_Unlock(VisRgn); REGION_Delete(CopyRgn);
GreDeleteObject(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) HRGN DcRgn = NtGdiCreateRectRgn(0, 0, 0, 0);
{ PREGION DcRgnObj = RGNOBJAPI_Lock(DcRgn, NULL);
RGNOBJAPI_Unlock(VisRgn);
}
/* /*
* Small trick here: there is no function to bitblt a region. So * Small trick here: there is no function to bitblt a region. So
@ -1929,9 +1915,11 @@ co_WinPosSetWindowPos(
* Since NtUserGetDCEx takes ownership of the clip region, we need * Since NtUserGetDCEx takes ownership of the clip region, we need
* to create a copy of CopyRgn and pass that. We need CopyRgn later * to create a copy of CopyRgn and pass that. We need CopyRgn later
*/ */
NtGdiOffsetRgn(CopyRgn, NewWindowRect.left, NewWindowRect.top); IntGdiCombineRgn(DcRgnObj, CopyRgn, NULL, RGN_COPY);
IntGdiOffsetRgn(DcRgnObj, NewWindowRect.left, NewWindowRect.top);
RGNOBJAPI_Unlock(DcRgnObj);
Dc = UserGetDCEx( Window, Dc = UserGetDCEx( Window,
CopyRgn, DcRgn,
DCX_WINDOW|DCX_CACHE|DCX_INTERSECTRGN|DCX_CLIPSIBLINGS|DCX_KEEPCLIPRGN); DCX_WINDOW|DCX_CACHE|DCX_INTERSECTRGN|DCX_CLIPSIBLINGS|DCX_KEEPCLIPRGN);
NtGdiBitBlt( Dc, NtGdiBitBlt( Dc,
CopyRect.left, CopyRect.top, CopyRect.left, CopyRect.top,
@ -1946,11 +1934,7 @@ co_WinPosSetWindowPos(
UserReleaseDC(Window, Dc, FALSE); UserReleaseDC(Window, Dc, FALSE);
IntValidateParent(Window, CopyRgn, FALSE); IntValidateParent(Window, CopyRgn, FALSE);
NtGdiOffsetRgn(CopyRgn, -NewWindowRect.left, -NewWindowRect.top); GreDeleteObject(DcRgn);
}
else if(VisRgn)
{
RGNOBJAPI_Unlock(VisRgn);
} }
} }
else else
@ -1961,14 +1945,16 @@ co_WinPosSetWindowPos(
/* We need to redraw what wasn't visible before */ /* We need to redraw what wasn't visible before */
if (VisAfter != NULL) if (VisAfter != NULL)
{ {
DirtyRgn = IntSysCreateRectRgn(0, 0, 0, 0); PREGION DirtyRgn = IntSysCreateRectpRgn(0, 0, 0, 0);
if (DirtyRgn)
{
if (CopyRgn != NULL) if (CopyRgn != NULL)
{ {
RgnType = NtGdiCombineRgn(DirtyRgn, VisAfter, CopyRgn, RGN_DIFF); RgnType = IntGdiCombineRgn(DirtyRgn, VisAfter, CopyRgn, RGN_DIFF);
} }
else else
{ {
RgnType = NtGdiCombineRgn(DirtyRgn, VisAfter, 0, RGN_COPY); RgnType = IntGdiCombineRgn(DirtyRgn, VisAfter, 0, RGN_COPY);
} }
if (RgnType != ERROR && RgnType != NULLREGION) if (RgnType != ERROR && RgnType != NULLREGION)
{ {
@ -1983,7 +1969,7 @@ co_WinPosSetWindowPos(
PWND Parent = Window->spwndParent; PWND Parent = Window->spwndParent;
NtGdiOffsetRgn( DirtyRgn, IntGdiOffsetRgn( DirtyRgn,
Window->rcWindow.left, Window->rcWindow.left,
Window->rcWindow.top); Window->rcWindow.top);
if ( (Window->style & WS_CHILD) && if ( (Window->style & WS_CHILD) &&
@ -2002,37 +1988,41 @@ co_WinPosSetWindowPos(
RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN); RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN);
} }
} }
GreDeleteObject(DirtyRgn); REGION_Delete(DirtyRgn);
}
} }
if (CopyRgn != NULL) if (CopyRgn != NULL)
{ {
GreDeleteObject(CopyRgn); REGION_Delete(CopyRgn);
} }
/* Expose what was covered before but not covered anymore */ /* Expose what was covered before but not covered anymore */
if (VisBefore != NULL) if (VisBefore != NULL)
{ {
ExposedRgn = IntSysCreateRectRgn(0, 0, 0, 0); PREGION ExposedRgn = IntSysCreateRectpRgn(0, 0, 0, 0);
RgnType = NtGdiCombineRgn(ExposedRgn, VisBefore, NULL, RGN_COPY); if (ExposedRgn)
NtGdiOffsetRgn( ExposedRgn, {
RgnType = IntGdiCombineRgn(ExposedRgn, VisBefore, NULL, RGN_COPY);
IntGdiOffsetRgn( ExposedRgn,
OldWindowRect.left - NewWindowRect.left, OldWindowRect.left - NewWindowRect.left,
OldWindowRect.top - NewWindowRect.top); OldWindowRect.top - NewWindowRect.top);
if (VisAfter != NULL) if (VisAfter != NULL)
RgnType = NtGdiCombineRgn(ExposedRgn, ExposedRgn, VisAfter, RGN_DIFF); RgnType = IntGdiCombineRgn(ExposedRgn, ExposedRgn, VisAfter, RGN_DIFF);
if (RgnType != ERROR && RgnType != NULLREGION) if (RgnType != ERROR && RgnType != NULLREGION)
{ {
co_VIS_WindowLayoutChanged(Window, ExposedRgn); co_VIS_WindowLayoutChanged(Window, ExposedRgn);
} }
GreDeleteObject(ExposedRgn); REGION_Delete(ExposedRgn);
GreDeleteObject(VisBefore); }
REGION_Delete(VisBefore);
} }
if (VisAfter != NULL) if (VisAfter != NULL)
{ {
GreDeleteObject(VisAfter); REGION_Delete(VisAfter);
} }
} }
@ -3112,7 +3102,7 @@ NtUserSetWindowRgn(
HRGN hRgn, HRGN hRgn,
BOOL bRedraw) BOOL bRedraw)
{ {
HRGN hrgnCopy; HRGN hrgnCopy = NULL;
PWND Window; PWND Window;
INT flags = (SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE); INT flags = (SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE);
BOOLEAN Ret = FALSE; BOOLEAN Ret = FALSE;
@ -3132,7 +3122,7 @@ NtUserSetWindowRgn(
{ {
if (GreIsHandleValid(hRgn)) if (GreIsHandleValid(hRgn))
{ {
hrgnCopy = IntSysCreateRectRgn(0, 0, 0, 0); hrgnCopy = NtGdiCreateRectRgn(0, 0, 0, 0);
/* The coordinates of a window's window region are relative to the /* The coordinates of a window's window region are relative to the
upper-left corner of the window, not the client area of the window. */ upper-left corner of the window, not the client area of the window. */
NtGdiCombineRgn( hrgnCopy, hRgn, 0, RGN_COPY); NtGdiCombineRgn( hrgnCopy, hRgn, 0, RGN_COPY);
@ -3140,10 +3130,6 @@ NtUserSetWindowRgn(
else else
RETURN( 0); RETURN( 0);
} }
else
{
hrgnCopy = NULL;
}
if (Window->hrgnClip) if (Window->hrgnClip)
{ {