*/
#include <win32k.h>
+#include <suppress.h>
#define NDEBUG
#include <debug.h>
INT
FASTCALL
-REGION_Complexity( PROSRGNDATA obj )
+REGION_Complexity(PREGION prgn)
{
- if (!obj) return NULLREGION;
- switch(obj->rdh.nCount)
+ if (!prgn) return NULLREGION;
+ switch(prgn->rdh.nCount)
{
- DPRINT("Region Complexity -> %lu",obj->rdh.nCount);
+ DPRINT("Region Complexity -> %lu", prgn->rdh.nCount);
case 0: return NULLREGION;
case 1: return SIMPLEREGION;
default: return COMPLEXREGION;
/***********************************************************************
* REGION_CropAndOffsetRegion
*/
-BOOL FASTCALL
+INT
+FASTCALL
REGION_CropAndOffsetRegion(
- PROSRGNDATA rgnDst,
- PROSRGNDATA rgnSrc,
+ PREGION rgnDst,
+ PREGION rgnSrc,
const RECTL *rect,
- const POINTL *offset
-)
+ const POINTL *offset) // FIXME: we should probably remove offset from here
{
POINT pt = {0,0};
const POINT *off = offset;
if (off->x || off->y)
xrect = rgnDst->Buffer;
else
- return TRUE;
+ return REGION_Complexity(rgnDst);
}
else
{
xrect = ExAllocatePoolWithTag(PagedPool, rgnSrc->rdh.nCount * sizeof(RECT), TAG_REGION);
if(!xrect)
- return FALSE;
+ return ERROR;
if (rgnDst->Buffer && rgnDst->Buffer != &rgnDst->rdh.rcBound)
ExFreePoolWithTag(rgnDst->Buffer, TAG_REGION); // Free the old buffer. Will be assigned to xrect below.
}
PRECTL temp;
temp = ExAllocatePoolWithTag(PagedPool, i * sizeof(RECT), TAG_REGION);
if (!temp)
- return FALSE;
+ return ERROR;
if (rgnDst->Buffer && rgnDst->Buffer != &rgnDst->rdh.rcBound)
ExFreePoolWithTag(rgnDst->Buffer, TAG_REGION); // free the old buffer
rgnDst->rdh.iType = RDH_RECTANGLES;
}
- return TRUE;
+ return REGION_Complexity(rgnDst);
empty:
if (!rgnDst->Buffer)
rgnDst->rdh.nRgnSize = RGN_DEFAULT_RECTS * sizeof(RECT);
}
else
- return FALSE;
+ return ERROR;
}
EMPTY_REGION(rgnDst);
- return TRUE;
+ return NULLREGION;
}
return FALSE;
}
- _PRAGMA_WARNING_SUPPRESS(28199) // rc is initialized
+ _PRAGMA_WARNING_SUPPRESS(__WARNING_MAYBE_UNINIT_VAR) // rc is initialized
COPY_RECTS(rgn->Buffer, rc, rgn->rdh.nCount);
}
}
}
+static
BOOL FASTCALL
REGION_LPTODP(
- PDC dc,
- HRGN hDest,
- HRGN hSrc)
+ _In_ PDC dc,
+ _Inout_ PREGION RgnDest,
+ _In_ PREGION RgnSrc)
{
RECTL *pCurRect, *pEndRect;
- PROSRGNDATA srcObj = NULL;
- PROSRGNDATA destObj = NULL;
-
RECTL tmpRect;
- BOOL ret = FALSE;
PDC_ATTR pdcattr;
if (!dc)
- return ret;
+ return FALSE;
pdcattr = dc->pdcattr;
if (pdcattr->iMapMode == MM_TEXT) // Requires only a translation
{
- if (NtGdiCombineRgn(hDest, hSrc, 0, RGN_COPY) == ERROR)
- goto done;
+ if (IntGdiCombineRgn(RgnDest, RgnSrc, 0, RGN_COPY) == ERROR)
+ return FALSE;
- NtGdiOffsetRgn(hDest, pdcattr->ptlViewportOrg.x - pdcattr->ptlWindowOrg.x,
+ IntGdiOffsetRgn(RgnDest, pdcattr->ptlViewportOrg.x - pdcattr->ptlWindowOrg.x,
pdcattr->ptlViewportOrg.y - pdcattr->ptlWindowOrg.y);
- ret = TRUE;
- goto done;
+ return TRUE;
}
- if ( !(srcObj = RGNOBJAPI_Lock(hSrc, NULL)) )
- goto done;
- if ( !(destObj = RGNOBJAPI_Lock(hDest, NULL)) )
- {
- RGNOBJAPI_Unlock(srcObj);
- goto done;
- }
- EMPTY_REGION(destObj);
+ EMPTY_REGION(RgnDest);
- pEndRect = srcObj->Buffer + srcObj->rdh.nCount;
- for (pCurRect = srcObj->Buffer; pCurRect < pEndRect; pCurRect++)
+ pEndRect = RgnSrc->Buffer + RgnSrc->rdh.nCount;
+ for (pCurRect = RgnSrc->Buffer; pCurRect < pEndRect; pCurRect++)
{
tmpRect = *pCurRect;
tmpRect.left = XLPTODP(pdcattr, tmpRect.left);
tmpRect.bottom = tmp;
}
- REGION_UnionRectWithRgn(destObj, &tmpRect);
+ REGION_UnionRectWithRgn(RgnDest, &tmpRect);
}
- ret = TRUE;
-
- RGNOBJAPI_Unlock(srcObj);
- RGNOBJAPI_Unlock(destObj);
-done:
- return ret;
+ return TRUE;
}
PROSRGNDATA
PREGION prgn;
/* 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)
{
return NULL;
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;
-}
-
-BOOL NTAPI
-REGION_Cleanup(PVOID ObjectBody)
+VOID NTAPI
+REGION_vCleanup(PVOID ObjectBody)
{
PROSRGNDATA pRgn = (PROSRGNDATA)ObjectBody;
PPROCESSINFO ppi = PsGetCurrentProcessWin32Process();
if (pRgn->Buffer && pRgn->Buffer != &pRgn->rdh.rcBound)
ExFreePoolWithTag(pRgn->Buffer, TAG_REGION);
- return TRUE;
}
VOID FASTCALL
VOID FASTCALL
IntGdiReleaseRaoRgn(PDC pDC)
{
- INT Index = GDI_HANDLE_GET_INDEX(pDC->BaseObject.hHmgr);
- PGDI_TABLE_ENTRY Entry = &GdiHandleTable->Entries[Index];
- pDC->fs |= DC_FLAG_DIRTY_RAO;
- Entry->Flags |= GDI_ENTRY_VALIDATE_VIS;
- RECTL_vSetEmptyRect(&pDC->erclClip);
+ INT Index = GDI_HANDLE_GET_INDEX(pDC->BaseObject.hHmgr);
+ PGDI_TABLE_ENTRY Entry = &GdiHandleTable->Entries[Index];
+ pDC->fs |= DC_FLAG_DIRTY_RAO;
+ Entry->Flags |= GDI_ENTRY_VALIDATE_VIS;
+ RECTL_vSetEmptyRect(&pDC->erclClip);
+ REGION_Delete(pDC->prgnRao);
+ pDC->prgnRao = NULL;
}
VOID FASTCALL
PRGN_ATTR prgnattr;
PPROCESSINFO ppi;
- prgn = REGION_LockRgn(hRgn);
+ prgn = RGNOBJAPI_Lock(hRgn, &prgnattr);
if (!prgn)
{
return FALSE;
}
- prgnattr = GDIOBJ_pvGetObjectAttr(&prgn->BaseObject);
- if (prgnattr)
+ if (prgnattr != &prgn->rgnattr)
{
GDIOBJ_vSetObjectAttr(&prgn->BaseObject, NULL);
- prgn->prgnattr = NULL;
+ prgn->prgnattr = &prgn->rgnattr;
ppi = PsGetCurrentProcessWin32Process();
GdiPoolFree(ppi->pPoolRgnAttr, prgnattr);
}
RGNOBJAPI_Unlock(prgn);
- return GreSetObjectOwner(hRgn, OwnerMask);
+ return GreSetObjectOwner(hRgn, OwnerMask);
}
INT
FASTCALL
IntGdiPaintRgn(
PDC dc,
- HRGN hRgn
+ PREGION Rgn
)
{
- HRGN tmpVisRgn;
- PROSRGNDATA visrgn;
- CLIPOBJ* ClipRegion;
+ PROSRGNDATA VisRgn;
+ XCLIPOBJ ClipRegion;
BOOL bRet = FALSE;
POINTL BrushOrigin;
SURFACE *psurf;
PDC_ATTR pdcattr;
- if (!dc) return FALSE;
+ if (!dc || !Rgn)
+ return FALSE;
+
pdcattr = dc->pdcattr;
ASSERT(!(pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY)));
- if (!(tmpVisRgn = IntSysCreateRectRgn(0, 0, 0, 0))) return FALSE;
-
- // Transform region into device co-ords
- if (!REGION_LPTODP(dc, tmpVisRgn, hRgn) ||
- NtGdiOffsetRgn(tmpVisRgn, dc->ptlDCOrig.x, dc->ptlDCOrig.y) == ERROR)
+ VisRgn = IntSysCreateRectpRgn(0, 0, 0, 0);
+ if (!VisRgn)
{
- GreDeleteObject(tmpVisRgn);
return FALSE;
}
- NtGdiCombineRgn(tmpVisRgn, tmpVisRgn, dc->rosdc.hGCClipRgn, RGN_AND);
-
- visrgn = RGNOBJAPI_Lock(tmpVisRgn, NULL);
- if (visrgn == NULL)
+ // Transform region into device co-ords
+ if (!REGION_LPTODP(dc, VisRgn, Rgn) ||
+ IntGdiOffsetRgn(VisRgn, dc->ptlDCOrig.x, dc->ptlDCOrig.y) == ERROR)
{
- GreDeleteObject(tmpVisRgn);
+ REGION_Delete(VisRgn);
return FALSE;
}
- ClipRegion = IntEngCreateClipRegion(visrgn->rdh.nCount,
- visrgn->Buffer,
- &visrgn->rdh.rcBound );
- ASSERT(ClipRegion);
+ if (dc->prgnRao)
+ IntGdiCombineRgn(VisRgn, VisRgn, dc->prgnRao, RGN_AND);
+
+ IntEngInitClipObj(&ClipRegion);
+ IntEngUpdateClipRegion(&ClipRegion, VisRgn->rdh.nCount, VisRgn->Buffer, &VisRgn->rdh.rcBound );
BrushOrigin.x = pdcattr->ptlBrushOrigin.x;
BrushOrigin.y = pdcattr->ptlBrushOrigin.y;
/* FIXME: Handle psurf == NULL !!!! */
bRet = IntEngPaint(&psurf->SurfObj,
- ClipRegion,
+ &ClipRegion.ClipObj,
&dc->eboFill.BrushObject,
&BrushOrigin,
0xFFFF); // FIXME: Don't know what to put here
- RGNOBJAPI_Unlock(visrgn);
- GreDeleteObject(tmpVisRgn);
+ REGION_Delete(VisRgn);
+ IntEngFreeClipResources(&ClipRegion);
// Fill the region
return bRet;
}
+BOOL
+FASTCALL
+REGION_PtInRegion(
+ PREGION prgn,
+ INT X,
+ INT Y)
+{
+ ULONG i;
+ PRECT r;
+
+ if (prgn->rdh.nCount > 0 && INRECT(prgn->rdh.rcBound, X, Y))
+ {
+ r = prgn->Buffer;
+ for (i = 0; i < prgn->rdh.nCount; i++)
+ {
+ if (INRECT(r[i], X, Y))
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
BOOL
FASTCALL
REGION_RectInRegion(
while (pSLLBlock)
{
tmpSLLBlock = pSLLBlock->next;
- ExFreePool(pSLLBlock);
+ ExFreePoolWithTag(pSLLBlock, TAG_REGION);
pSLLBlock = tmpSLLBlock;
}
}
numRects = ((numFullPtBlocks * NUMPTSTOBUFFER) + iCurPtBlock) >> 1;
+ /* Make sure, we have at least one rect */
+ if (numRects == 0)
+ {
+ numRects = 1;
+ }
+
if (!(temp = ExAllocatePoolWithTag(PagedPool, numRects * sizeof(RECT), TAG_REGION)))
{
return 0;
}
}
-HRGN FASTCALL
-IntCreatePolyPolygonRgn(
+BOOL FASTCALL
+IntSetPolyPolygonRgn(
POINT *Pts,
PULONG Count,
INT nbpolygons,
- INT mode
+ INT mode,
+ PREGION Rgn
)
{
- HRGN hrgn;
- ROSRGNDATA *region;
EdgeTableEntry *pAET; /* Active Edge Table */
INT y; /* Current scanline */
int iPts = 0; /* Number of pts in buffer */
if (mode == 0 || mode > 2) return 0;
- if (!(region = REGION_AllocUserRgnWithHandle(nbpolygons)))
- return 0;
- hrgn = region->BaseObject.hHmgr;
-
/* Special case a rectangle */
if (((nbpolygons == 1) && ((*Count == 4) ||
(Pts[2].x == Pts[3].x) &&
(Pts[3].y == Pts[0].y))))
{
- RGNOBJAPI_Unlock(region);
- NtGdiSetRectRgn(hrgn, min(Pts[0].x, Pts[2].x), min(Pts[0].y, Pts[2].y),
- max(Pts[0].x, Pts[2].x), max(Pts[0].y, Pts[2].y));
- return hrgn;
+ REGION_SetRectRgn(Rgn,
+ min(Pts[0].x, Pts[2].x),
+ min(Pts[0].y, Pts[2].y),
+ max(Pts[0].x, Pts[2].x),
+ max(Pts[0].y, Pts[2].y));
+ return TRUE;
}
for (poly = total = 0; poly < nbpolygons; poly++)
total += Count[poly];
if (! (pETEs = ExAllocatePoolWithTag(PagedPool, sizeof(EdgeTableEntry) * total, TAG_REGION)) )
{
- GreDeleteObject(hrgn);
- return 0;
+ return FALSE;
}
pts = FirstPtBlock.pts;
REGION_CreateETandAET(Count, nbpolygons, Pts, &ET, &AET, pETEs, &SLLBlock);
{
DPRINT1("Can't alloc tPB\n");
ExFreePoolWithTag(pETEs, TAG_REGION);
- return 0;
+ return FALSE;
}
curPtBlock->next = tmpPtBlock;
curPtBlock = tmpPtBlock;
{
DPRINT1("Can't alloc tPB\n");
ExFreePoolWithTag(pETEs, TAG_REGION);
- GreDeleteObject(hrgn);
- return 0;
+ return FALSE;
}
curPtBlock->next = tmpPtBlock;
curPtBlock = tmpPtBlock;
}
}
REGION_FreeStorage(SLLBlock.next);
- REGION_PtsToRegion(numFullPtBlocks, iPts, &FirstPtBlock, region);
+ REGION_PtsToRegion(numFullPtBlocks, iPts, &FirstPtBlock, Rgn);
for (curPtBlock = FirstPtBlock.next; --numFullPtBlocks >= 0;)
{
curPtBlock = tmpPtBlock;
}
ExFreePoolWithTag(pETEs, TAG_REGION);
- RGNOBJAPI_Unlock(region);
- return hrgn;
+ return TRUE;
}
BOOL
REGION_SetRectRgn(pRgn, LeftRect, TopRect, RightRect, BottomRect);
RGNOBJAPI_Unlock(pRgn);
+ DPRINT("Returning %p.\n", hRgn);
+
return hRgn;
}
DWORD nCount = 0;
DWORD iType = 0;
DWORD dwSize = 0;
+ UINT i;
+ RECT* rects;
NTSTATUS Status = STATUS_SUCCESS;
MATRIX matrix;
XFORMOBJ xo;
nCount = RgnData->rdh.nCount;
iType = RgnData->rdh.iType;
dwSize = RgnData->rdh.dwSize;
+ rects = (RECT*)RgnData->Buffer;
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
_SEH2_TRY
{
+ /* Insert the rectangles one by one */
+ for(i=0; i<nCount; i++)
+ {
+ REGION_UnionRectWithRgn(Region, &rects[i]);
+ }
if (Xform)
{
ULONG ret;
/* Apply the coordinate transformation on the rects */
if (XFORMOBJ_bApplyXform(&xo,
XF_LTOL,
- nCount * 2,
- RgnData->Buffer,
+ Region->rdh.nCount * 2,
+ Region->Buffer,
Region->Buffer))
{
Status = STATUS_SUCCESS;
}
}
}
- else
- {
- /* Copy rect coordinates */
- RtlCopyMemory(Region->Buffer,
- RgnData->Buffer,
- nCount * sizeof(RECT));
- }
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
HRGN FrameRgn;
BOOL Ret;
- if (!(FrameRgn = IntSysCreateRectRgn(0, 0, 0, 0)))
+ if (!(FrameRgn = NtGdiCreateRectRgn(0, 0, 0, 0)))
{
return FALSE;
}
INT Y
)
{
- PROSRGNDATA rgn;
- ULONG i;
- PRECTL r;
+ PREGION prgn;
+ BOOL ret;
- if (!(rgn = RGNOBJAPI_Lock(hRgn, NULL) ) )
+ if (!(prgn = RGNOBJAPI_Lock(hRgn, NULL) ) )
return FALSE;
- if (rgn->rdh.nCount > 0 && INRECT(rgn->rdh.rcBound, X, Y))
- {
- r = rgn->Buffer;
- for (i = 0; i < rgn->rdh.nCount; i++)
- {
- if (INRECT(*r, X, Y))
- {
- RGNOBJAPI_Unlock(rgn);
- return TRUE;
- }
- r++;
- }
- }
- RGNOBJAPI_Unlock(rgn);
- return FALSE;
+ ret = REGION_PtInRegion(prgn, X, Y);
+
+ RGNOBJAPI_Unlock(prgn);
+ return ret;
}
BOOL
*
* If the function fails, the return value is zero."
*/
-DWORD APIENTRY
+_Success_(return!=0)
+ULONG
+APIENTRY
NtGdiGetRegionData(
- HRGN hrgn,
- DWORD count,
- LPRGNDATA rgndata
-)
+ _In_ HRGN hrgn,
+ _In_ ULONG cjBuffer,
+ _Out_opt_bytecap_(cjBuffer) LPRGNDATA lpRgnData)
{
- DWORD size;
- PROSRGNDATA obj = RGNOBJAPI_Lock(hrgn, NULL);
- NTSTATUS Status = STATUS_SUCCESS;
-
- if (!obj)
- return 0;
+ ULONG cjRects, cjSize;
+ PREGION prgn;
- size = obj->rdh.nCount * sizeof(RECT);
- if (count < (size + sizeof(RGNDATAHEADER)) || rgndata == NULL)
+ /* Lock the region */
+ prgn = RGNOBJAPI_Lock(hrgn, NULL);
+ if (!prgn)
{
- RGNOBJAPI_Unlock(obj);
- if (rgndata) /* Buffer is too small, signal it by return 0 */
- return 0;
- else /* User requested buffer size with rgndata NULL */
- return size + sizeof(RGNDATAHEADER);
+ EngSetLastError(ERROR_INVALID_HANDLE);
+ return 0;
}
- _SEH2_TRY
- {
- ProbeForWrite(rgndata, count, 1);
- RtlCopyMemory(rgndata, &obj->rdh, sizeof(RGNDATAHEADER));
- RtlCopyMemory(rgndata->Buffer, obj->Buffer, size);
- }
- _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
- {
- Status = _SEH2_GetExceptionCode();
- }
- _SEH2_END;
+ /* Calculate the region sizes */
+ cjRects = prgn->rdh.nCount * sizeof(RECT);
+ cjSize = cjRects + sizeof(RGNDATAHEADER);
- if (!NT_SUCCESS(Status))
+ /* Check if region data is requested */
+ if (lpRgnData)
{
- SetLastNtError(Status);
- RGNOBJAPI_Unlock(obj);
- return 0;
+ /* Check if the buffer is large enough */
+ if (cjBuffer >= cjSize)
+ {
+ /* Probe the buffer and copy the data */
+ _SEH2_TRY
+ {
+ ProbeForWrite(lpRgnData, cjSize, sizeof(ULONG));
+ RtlCopyMemory(lpRgnData, &prgn->rdh, sizeof(RGNDATAHEADER));
+ RtlCopyMemory(lpRgnData->Buffer, prgn->Buffer, cjRects);
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ EngSetLastError(ERROR_INVALID_PARAMETER);
+ cjSize = 0;
+ }
+ _SEH2_END;
+ }
+ else
+ {
+ /* Buffer is too small */
+ EngSetLastError(ERROR_INVALID_PARAMETER);
+ cjSize = 0;
+ }
}
- RGNOBJAPI_Unlock(obj);
- return size + sizeof(RGNDATAHEADER);
+ /* Unlock the region and return the size */
+ RGNOBJAPI_Unlock(prgn);
+ return cjSize;
}
/* EOF */