From 7ea71b67f4d5e2753070d8f752d3eb6de9c3f2bb Mon Sep 17 00:00:00 2001 From: Thomas Bluemel Date: Tue, 18 May 2004 13:57:41 +0000 Subject: [PATCH] safe parameter handling for PolyPolygonRgn() and PolygonRgn(). The actual region calculation for both functions is not yet implemented though! svn path=/trunk/; revision=9436 --- reactos/lib/gdi32/misc/stubs.c | 18 +-- reactos/lib/gdi32/objects/region.c | 24 +++- reactos/subsys/win32k/objects/region.c | 161 +++++++++++++++++++++++-- 3 files changed, 176 insertions(+), 27 deletions(-) diff --git a/reactos/lib/gdi32/misc/stubs.c b/reactos/lib/gdi32/misc/stubs.c index 36e80a40215..5b163624222 100644 --- a/reactos/lib/gdi32/misc/stubs.c +++ b/reactos/lib/gdi32/misc/stubs.c @@ -1,4 +1,4 @@ -/* $Id: stubs.c,v 1.61 2004/05/15 08:52:25 navaraf Exp $ +/* $Id: stubs.c,v 1.62 2004/05/18 13:57:41 weiden Exp $ * * reactos/lib/gdi32/misc/stubs.c * @@ -1091,22 +1091,6 @@ GetMiterLimit( return FALSE; } - -/* - * @unimplemented - */ -HRGN -STDCALL -CreatePolygonRgn( - CONST POINT *a0, - int a1, - int a2 - ) -{ - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return 0; -} - /* * @unimplemented */ diff --git a/reactos/lib/gdi32/objects/region.c b/reactos/lib/gdi32/objects/region.c index 352e43d3b47..cfcd00f5960 100644 --- a/reactos/lib/gdi32/objects/region.c +++ b/reactos/lib/gdi32/objects/region.c @@ -85,8 +85,27 @@ CreatePolyPolygonRgn( int fnPolyFillMode ) { - return NtGdiCreatePolyPolygonRgn ( (CONST PPOINT)lppt, - (CONST PINT)lpPolyCounts, nCount, fnPolyFillMode ); + return NtGdiCreatePolyPolygonRgn((CONST PPOINT)lppt, + (CONST PINT)lpPolyCounts, + nCount, + fnPolyFillMode); +} + + +/* + * @implemented + */ +HRGN +STDCALL +CreatePolygonRgn( + CONST POINT *lppt, + int cPoints, + int fnPolyFillMode + ) +{ + return NtGdiCreatePolygonRgn((CONST PPOINT)lppt, + cPoints, + fnPolyFillMode); } @@ -312,3 +331,4 @@ FrameRgn( { return NtGdiFrameRgn(hdc, hrgn, hbr, nWidth, nHeight); } + diff --git a/reactos/subsys/win32k/objects/region.c b/reactos/subsys/win32k/objects/region.c index b095dff8fb7..649ef0c052a 100644 --- a/reactos/subsys/win32k/objects/region.c +++ b/reactos/subsys/win32k/objects/region.c @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* $Id: region.c,v 1.53 2004/05/16 09:51:27 weiden Exp $ */ +/* $Id: region.c,v 1.54 2004/05/18 13:57:41 weiden Exp $ */ #include #include @@ -1692,23 +1692,168 @@ NtGdiCreateEllipticRgnIndirect(CONST PRECT Rect) SafeRect.right - SafeRect.left, SafeRect.bottom - SafeRect.top); } +HRGN FASTCALL +IntCreatePolyPolgonRgn(PPOINT pt, + PINT PolyCounts, + INT Count, + INT PolyFillMode) +{ + return (HRGN)0; +} + HRGN STDCALL NtGdiCreatePolygonRgn(CONST PPOINT pt, - INT Count, - INT PolyFillMode) + INT Count, + INT PolyFillMode) { - UNIMPLEMENTED; + POINT *SafePoints; + NTSTATUS Status; + HRGN hRgn; + + + if (pt == NULL || Count == 0 || + (PolyFillMode != WINDING && PolyFillMode != ALTERNATE)) + { + /* Windows doesn't set a last error here */ + return (HRGN)0; + } + + if (Count == 1) + { + /* can't create a region with only one point! */ + SetLastWin32Error(ERROR_INVALID_PARAMETER); + return (HRGN)0; + } + + if (Count == 2) + { + /* Windows creates an empty region! */ + ROSRGNDATA *rgn; + + if(!(hRgn = RGNDATA_AllocRgn(1))) + { + return (HRGN)0; + } + if(!(rgn = RGNDATA_LockRgn(hRgn))) + { + NtGdiDeleteObject(hRgn); + return (HRGN)0; + } + + EMPTY_REGION(rgn); + + RGNDATA_UnlockRgn(hRgn); + return hRgn; + } + + if (!(SafePoints = ExAllocatePool(PagedPool, Count * sizeof(POINT)))) + { + SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY); + return (HRGN)0; + } + + Status = MmCopyFromCaller(SafePoints, pt, Count * sizeof(POINT)); + if (!NT_SUCCESS(Status)) + { + ExFreePool(SafePoints); + SetLastNtError(Status); + return (HRGN)0; + } + + hRgn = IntCreatePolyPolgonRgn(SafePoints, &Count, 1, PolyFillMode); + + ExFreePool(SafePoints); + return hRgn; } HRGN STDCALL NtGdiCreatePolyPolygonRgn(CONST PPOINT pt, - CONST PINT PolyCounts, - INT Count, - INT PolyFillMode) + CONST PINT PolyCounts, + INT Count, + INT PolyFillMode) { - UNIMPLEMENTED; + POINT *Safept; + INT *SafePolyCounts; + INT nPoints, nEmpty, nInvalid, i; + HRGN hRgn; + NTSTATUS Status; + + if (pt == NULL || PolyCounts == NULL || Count == 0 || + (PolyFillMode != WINDING && PolyFillMode != ALTERNATE)) + { + /* Windows doesn't set a last error here */ + return (HRGN)0; + } + + if (!(SafePolyCounts = ExAllocatePool(PagedPool, Count * sizeof(INT)))) + { + SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY); + return (HRGN)0; + } + + Status = MmCopyFromCaller(SafePolyCounts, PolyCounts, Count * sizeof(INT)); + if (!NT_SUCCESS(Status)) + { + ExFreePool(SafePolyCounts); + SetLastNtError(Status); + return (HRGN)0; + } + + /* validate poligons */ + nPoints = 0; + nEmpty = 0; + nInvalid = 0; + for (i = 0; i < Count; i++) + { + if (SafePolyCounts[i] == 0) + { + nEmpty++; + } + if (SafePolyCounts[i] == 1) + { + nInvalid++; + } + nPoints += SafePolyCounts[i]; + } + + if (nEmpty == Count) + { + /* if all polygon counts are zero, return without setting a last error code. */ + ExFreePool(SafePolyCounts); + return (HRGN)0; + } + if (nInvalid != 0) + { + /* if at least one poly count is 1, fail */ + ExFreePool(SafePolyCounts); + SetLastWin32Error(ERROR_INVALID_PARAMETER); + return (HRGN)0; + } + + /* copy points */ + if (!(Safept = ExAllocatePool(PagedPool, nPoints * sizeof(POINT)))) + { + SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY); + return (HRGN)0; + } + + Status = MmCopyFromCaller(Safept, pt, nPoints * sizeof(POINT)); + if (!NT_SUCCESS(Status)) + { + ExFreePool(Safept); + ExFreePool(SafePolyCounts); + SetLastNtError(Status); + return (HRGN)0; + } + + /* now we're ready to calculate the region safely */ + hRgn = IntCreatePolyPolgonRgn(Safept, SafePolyCounts, Count, PolyFillMode); + + ExFreePool(Safept); + ExFreePool(SafePolyCounts); + return hRgn; } HRGN STDCALL