diff --git a/reactos/subsystems/win32/win32k/include/intgdi.h b/reactos/subsystems/win32/win32k/include/intgdi.h index 03bf496c08b..507de8759f4 100644 --- a/reactos/subsystems/win32/win32k/include/intgdi.h +++ b/reactos/subsystems/win32/win32k/include/intgdi.h @@ -93,7 +93,7 @@ IntGdiPolyBezierTo(DC *dc, BOOL FASTCALL IntGdiPolyPolyline(DC *dc, LPPOINT pt, - LPDWORD PolyPoints, + PULONG PolyPoints, DWORD Count); BOOL FASTCALL @@ -125,7 +125,7 @@ IntGdiPolygon(PDC dc, BOOL FASTCALL IntGdiPolyPolygon(DC *dc, LPPOINT Points, - LPINT PolyCounts, + PULONG PolyCounts, int Count); BOOL FASTCALL IntGdiGradientFill(DC *dc, diff --git a/reactos/subsystems/win32/win32k/include/region.h b/reactos/subsystems/win32/win32k/include/region.h index 14aa163aab0..3c075b14c04 100644 --- a/reactos/subsystems/win32/win32k/include/region.h +++ b/reactos/subsystems/win32/win32k/include/region.h @@ -43,7 +43,7 @@ VOID FASTCALL IntGdiReleaseVisRgn(PDC); INT STDCALL IntGdiGetRgnBox(HRGN, LPRECT); BOOL FASTCALL IntGdiPaintRgn(PDC, HRGN ); -HRGN FASTCALL GdiCreatePolyPolygonRgn(CONST PPOINT, CONST PINT, INT, INT ); +HRGN FASTCALL IntCreatePolyPolygonRgn(PPOINT, PULONG, INT, INT); INT FASTCALL IntGdiCombineRgn(PROSRGNDATA, PROSRGNDATA, PROSRGNDATA, INT); INT FASTCALL REGION_Complexity(PROSRGNDATA); diff --git a/reactos/subsystems/win32/win32k/objects/fillshap.c b/reactos/subsystems/win32/win32k/objects/fillshap.c index 4e0a3f2ce68..52ab9260410 100644 --- a/reactos/subsystems/win32/win32k/objects/fillshap.c +++ b/reactos/subsystems/win32/win32k/objects/fillshap.c @@ -51,7 +51,7 @@ BOOL FASTCALL IntDrawRoundRect( PDC dc, INT Left, INT Top, INT Right, INT Bottom BOOL FASTCALL IntGdiPolygon(PDC dc, - PPOINT UnsafePoints, + PPOINT Points, int Count) { BITMAPOBJ *BitmapObj; @@ -64,7 +64,7 @@ IntGdiPolygon(PDC dc, ASSERT(dc); // caller's responsibility to pass a valid dc - if ( NULL == UnsafePoints || Count < 2 ) + if (!Points || Count < 2 ) { SetLastWin32Error(ERROR_INVALID_PARAMETER); return FALSE; @@ -74,25 +74,25 @@ IntGdiPolygon(PDC dc, if (!Dc_Attr) Dc_Attr = &dc->Dc_Attr; /* Convert to screen coordinates */ - IntLPtoDP(dc, UnsafePoints, Count); + IntLPtoDP(dc, Points, Count); for (CurrentPoint = 0; CurrentPoint < Count; CurrentPoint++) { - UnsafePoints[CurrentPoint].x += dc->ptlDCOrig.x; - UnsafePoints[CurrentPoint].y += dc->ptlDCOrig.y; + Points[CurrentPoint].x += dc->ptlDCOrig.x; + Points[CurrentPoint].y += dc->ptlDCOrig.y; } // No need to have path here. { - DestRect.left = UnsafePoints[0].x; - DestRect.right = UnsafePoints[0].x; - DestRect.top = UnsafePoints[0].y; - DestRect.bottom = UnsafePoints[0].y; + DestRect.left = Points[0].x; + DestRect.right = Points[0].x; + DestRect.top = Points[0].y; + DestRect.bottom = Points[0].y; for (CurrentPoint = 1; CurrentPoint < Count; ++CurrentPoint) { - DestRect.left = min(DestRect.left, UnsafePoints[CurrentPoint].x); - DestRect.right = max(DestRect.right, UnsafePoints[CurrentPoint].x); - DestRect.top = min(DestRect.top, UnsafePoints[CurrentPoint].y); - DestRect.bottom = max(DestRect.bottom, UnsafePoints[CurrentPoint].y); + DestRect.left = min(DestRect.left, Points[CurrentPoint].x); + DestRect.right = max(DestRect.right, Points[CurrentPoint].x); + DestRect.top = min(DestRect.top, Points[CurrentPoint].y); + DestRect.bottom = max(DestRect.bottom, Points[CurrentPoint].y); } /* Special locking order to avoid lock-ups */ @@ -106,7 +106,7 @@ IntGdiPolygon(PDC dc, if (FillBrushObj && !(FillBrushObj->flAttrs & GDIBRUSH_IS_NULL)) { IntGdiInitBrushInstance(&FillBrushInst, FillBrushObj, dc->XlateBrush); - ret = FillPolygon ( dc, BitmapObj, &FillBrushInst.BrushObject, ROP2_TO_MIX(Dc_Attr->jROP2), UnsafePoints, Count, DestRect ); + ret = FillPolygon ( dc, BitmapObj, &FillBrushInst.BrushObject, ROP2_TO_MIX(Dc_Attr->jROP2), Points, Count, DestRect ); } if (FillBrushObj) BRUSHOBJ_UnlockBrush(FillBrushObj); @@ -122,16 +122,16 @@ IntGdiPolygon(PDC dc, { // DPRINT1("Polygon Making line from (%d,%d) to (%d,%d)\n", -// UnsafePoints[0].x, UnsafePoints[0].y, -// UnsafePoints[1].x, UnsafePoints[1].y ); +// Points[0].x, Points[0].y, +// Points[1].x, Points[1].y ); ret = IntEngLineTo(&BitmapObj->SurfObj, dc->CombinedClip, &PenBrushInst.BrushObject, - UnsafePoints[i].x, /* From */ - UnsafePoints[i].y, - UnsafePoints[i+1].x, /* To */ - UnsafePoints[i+1].y, + Points[i].x, /* From */ + Points[i].y, + Points[i+1].x, /* To */ + Points[i+1].y, &DestRect, ROP2_TO_MIX(Dc_Attr->jROP2)); /* MIX */ if (!ret) break; @@ -142,10 +142,10 @@ IntGdiPolygon(PDC dc, ret = IntEngLineTo(&BitmapObj->SurfObj, dc->CombinedClip, &PenBrushInst.BrushObject, - UnsafePoints[Count-1].x, /* From */ - UnsafePoints[Count-1].y, - UnsafePoints[0].x, /* To */ - UnsafePoints[0].y, + Points[Count-1].x, /* From */ + Points[Count-1].y, + Points[0].x, /* To */ + Points[0].y, &DestRect, ROP2_TO_MIX(Dc_Attr->jROP2)); /* MIX */ } @@ -161,11 +161,11 @@ IntGdiPolygon(PDC dc, BOOL FASTCALL IntGdiPolyPolygon(DC *dc, LPPOINT Points, - LPINT PolyCounts, + PULONG PolyCounts, int Count) { if (PATH_IsPathOpen(dc->DcLevel)) - return PATH_PolyPolygon ( dc, Points, PolyCounts, Count); + return PATH_PolyPolygon ( dc, Points, (PINT)PolyCounts, Count); while (--Count >=0) { @@ -336,185 +336,152 @@ extern BOOL FillPolygon(PDC dc, ULONG_PTR STDCALL NtGdiPolyPolyDraw( IN HDC hDC, - IN PPOINT Points, - IN PULONG PolyCounts, + IN PPOINT UnsafePoints, + IN PULONG UnsafeCounts, IN ULONG Count, IN INT iFunc ) { DC *dc; - LPPOINT Safept; - LPINT SafePolyPoints; + PVOID pTemp; + LPPOINT SafePoints; + PULONG SafeCounts; NTSTATUS Status = STATUS_SUCCESS; BOOL Ret = TRUE; - INT nPoints, nEmpty, nInvalid, i; + INT nPoints = 0, nMaxPoints = 0, nInvalid = 0, i; - if (iFunc == GdiPolyPolyRgn) + if (!UnsafePoints || !UnsafeCounts || + Count == 0 || iFunc == 0 || iFunc > GdiPolyPolyRgn) { - return (ULONG_PTR) GdiCreatePolyPolygonRgn((CONST PPOINT) Points, - (CONST PINT) PolyCounts, - Count, - (INT) hDC); - } - dc = DC_LockDc(hDC); - if (!dc) - { - SetLastWin32Error(ERROR_INVALID_HANDLE); + /* Windows doesn't set last error */ return FALSE; } - if (dc->DC_Type == DC_TYPE_INFO) + + _SEH_TRY { - DC_UnlockDc(dc); - /* Yes, Windows really returns TRUE in this case */ - return TRUE; - } + ProbeForRead(UnsafePoints, Count * sizeof(POINT), 1); + ProbeForRead(UnsafeCounts, Count * sizeof(ULONG), 1); - if (Count > 0) - { - _SEH_TRY - { - ProbeForRead(Points, - Count * sizeof(POINT), - 1); - ProbeForRead(PolyCounts, - Count * sizeof(INT), - 1); - } - _SEH_HANDLE - { - Status = _SEH_GetExceptionCode(); - } - _SEH_END; - - if (!NT_SUCCESS(Status)) - { - DC_UnlockDc(dc); - SetLastNtError(Status); - return FALSE; - } - - SafePolyPoints = ExAllocatePoolWithTag(PagedPool, Count * sizeof(INT), TAG_SHAPE); - if (!SafePolyPoints) - { - DC_UnlockDc(dc); - SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY); - return FALSE; - } - - _SEH_TRY - { - /* pointers already probed! */ - RtlCopyMemory(SafePolyPoints, - PolyCounts, - Count * sizeof(INT)); - } - _SEH_HANDLE - { - Status = _SEH_GetExceptionCode(); - } - _SEH_END; - - if (!NT_SUCCESS(Status)) - { - DC_UnlockDc(dc); - ExFreePool(SafePolyPoints); - SetLastNtError(Status); - return FALSE; - } - /* validate poligons */ - nPoints = 0; - nEmpty = 0; - nInvalid = 0; + /* Count points and validate poligons */ for (i = 0; i < Count; i++) { - if (SafePolyPoints[i] == 0) - { - nEmpty++; - } - if (SafePolyPoints[i] == 1) + if (UnsafeCounts[i] < 2) { nInvalid++; } - nPoints += SafePolyPoints[i]; - } - - if (nEmpty == Count) - { - /* if all polygon counts are zero, return without setting a last error code. */ - ExFreePool(SafePolyPoints); - return FALSE; - } - if (nInvalid != 0) - { - /* if at least one poly count is 1, fail */ - ExFreePool(SafePolyPoints); - SetLastWin32Error(ERROR_INVALID_PARAMETER); - return FALSE; - } - - Safept = ExAllocatePoolWithTag(PagedPool, nPoints * sizeof(POINT), TAG_SHAPE); - if (!Safept) - { - DC_UnlockDc(dc); - ExFreePool(SafePolyPoints); - SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY); - return FALSE; - } - - _SEH_TRY - { - /* pointers already probed! */ - RtlCopyMemory(Safept, - Points, - nPoints * sizeof(POINT)); - } - _SEH_HANDLE - { - Status = _SEH_GetExceptionCode(); - } - _SEH_END; - - if (!NT_SUCCESS(Status)) - { - DC_UnlockDc(dc); - ExFreePool(SafePolyPoints); - ExFreePool(Safept); - SetLastNtError(Status); - return FALSE; + nPoints += UnsafeCounts[i]; + nMaxPoints = max(nMaxPoints, UnsafeCounts[i]); } } - else + _SEH_HANDLE { - DC_UnlockDc(dc); + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + + if (!NT_SUCCESS(Status)) + { + /* Windows doesn't set last error */ + return FALSE; + } + + if (nPoints == 0 || nPoints < nMaxPoints) + { + /* If all polygon counts are zero, or we have overflow, + return without setting a last error code. */ + return FALSE; + } + + if (nInvalid != 0) + { + /* If at least one poly count is 0 or 1, fail */ SetLastWin32Error(ERROR_INVALID_PARAMETER); return FALSE; } + /* Allocate one buffer for both counts and points */ + pTemp = ExAllocatePoolWithTag(PagedPool, + Count * sizeof(ULONG) + nPoints * sizeof(POINT), + TAG_SHAPE); + if (!pTemp) + { + SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY); + return FALSE; + } + + SafeCounts = pTemp; + SafePoints = (PVOID)(SafeCounts + Count); + + _SEH_TRY + { + /* Pointers already probed! */ + RtlCopyMemory(SafeCounts, UnsafeCounts, Count * sizeof(ULONG)); + RtlCopyMemory(SafePoints, UnsafePoints, nPoints * sizeof(POINT)); + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + + if (!NT_SUCCESS(Status)) + { + ExFreePool(pTemp); + return FALSE; + } + + /* Special handling for GdiPolyPolyRgn */ + if (iFunc == GdiPolyPolyRgn) + { + HRGN hRgn; + hRgn = IntCreatePolyPolygonRgn(SafePoints, SafeCounts, Count, (INT_PTR)hDC); + ExFreePool(pTemp); + return (ULONG_PTR)hRgn; + } + + dc = DC_LockDc(hDC); + if (!dc) + { + SetLastWin32Error(ERROR_INVALID_HANDLE); + ExFreePool(pTemp); + return FALSE; + } + + if (dc->DC_Type == DC_TYPE_INFO) + { + DC_UnlockDc(dc); + ExFreePool(pTemp); + /* Yes, Windows really returns TRUE in this case */ + return TRUE; + } + + /* Perform the actual work */ switch (iFunc) { case GdiPolyPolygon: - Ret = IntGdiPolyPolygon(dc, Safept, SafePolyPoints, Count); + Ret = IntGdiPolyPolygon(dc, SafePoints, SafeCounts, Count); break; case GdiPolyPolyLine: - Ret = IntGdiPolyPolyline(dc, Safept, (LPDWORD) SafePolyPoints, Count); + Ret = IntGdiPolyPolyline(dc, SafePoints, SafeCounts, Count); break; case GdiPolyBezier: - Ret = IntGdiPolyBezier(dc, Safept, *PolyCounts); + Ret = IntGdiPolyBezier(dc, SafePoints, *SafeCounts); break; case GdiPolyLineTo: - Ret = IntGdiPolylineTo(dc, Safept, *PolyCounts); + Ret = IntGdiPolylineTo(dc, SafePoints, *SafeCounts); break; case GdiPolyBezierTo: - Ret = IntGdiPolyBezierTo(dc, Safept, *PolyCounts); + Ret = IntGdiPolyBezierTo(dc, SafePoints, *SafeCounts); break; default: SetLastWin32Error(ERROR_INVALID_PARAMETER); Ret = FALSE; } - ExFreePool(SafePolyPoints); - ExFreePool(Safept); - DC_UnlockDc(dc); - return (ULONG_PTR) Ret; + /* Cleanup and return */ + DC_UnlockDc(dc); + ExFreePool(pTemp); + + return (ULONG_PTR)Ret; } diff --git a/reactos/subsystems/win32/win32k/objects/line.c b/reactos/subsystems/win32/win32k/objects/line.c index 66fce7a7ab9..aac2748f2f3 100644 --- a/reactos/subsystems/win32/win32k/objects/line.c +++ b/reactos/subsystems/win32/win32k/objects/line.c @@ -350,12 +350,12 @@ IntGdiPolylineTo(DC *dc, BOOL FASTCALL IntGdiPolyPolyline(DC *dc, LPPOINT pt, - LPDWORD PolyPoints, + PULONG PolyPoints, DWORD Count) { int i; LPPOINT pts; - LPDWORD pc; + PULONG pc; BOOL ret = FALSE; // default to failure pts = pt; pc = PolyPoints; diff --git a/reactos/subsystems/win32/win32k/objects/path.c b/reactos/subsystems/win32/win32k/objects/path.c index a17270e92c1..7c9ac01ab36 100644 --- a/reactos/subsystems/win32/win32k/objects/path.c +++ b/reactos/subsystems/win32/win32k/objects/path.c @@ -1028,7 +1028,6 @@ PATH_FlattenPath(PPATH pPath) } -HRGN FASTCALL IntCreatePolyPolygonRgn(POINT *Pts, INT *Count, INT nbpolygons,INT mode); /* PATH_PathToRegion * * Creates a region from the specified path using the specified polygon @@ -1042,7 +1041,7 @@ FASTCALL PATH_PathToRegion ( PPATH pPath, INT nPolyFillMode, HRGN *pHrgn ) { int numStrokes, iStroke, i; - INT *pNumPointsInStroke; + PULONG pNumPointsInStroke; HRGN hrgn = 0; ASSERT(pPath!=NULL); @@ -1060,7 +1059,7 @@ PATH_PathToRegion ( PPATH pPath, INT nPolyFillMode, HRGN *pHrgn ) numStrokes++; /* Allocate memory for number-of-points-in-stroke array */ - pNumPointsInStroke=(int *)ExAllocatePoolWithTag(PagedPool, sizeof(int) * numStrokes, TAG_PATH); + pNumPointsInStroke = ExAllocatePoolWithTag(PagedPool, sizeof(ULONG) * numStrokes, TAG_PATH); if(!pNumPointsInStroke) { SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY); diff --git a/reactos/subsystems/win32/win32k/objects/region.c b/reactos/subsystems/win32/win32k/objects/region.c index e5129497310..80864b56fcf 100644 --- a/reactos/subsystems/win32/win32k/objects/region.c +++ b/reactos/subsystems/win32/win32k/objects/region.c @@ -3560,7 +3560,7 @@ REGION_PtsToRegion( */ static void FASTCALL REGION_CreateETandAET( - const INT *Count, + const ULONG *Count, INT nbpolygons, const POINT *pts, EdgeTable *ET, @@ -3657,7 +3657,7 @@ REGION_CreateETandAET( HRGN FASTCALL IntCreatePolyPolygonRgn( POINT *Pts, - INT *Count, + PULONG Count, INT nbpolygons, INT mode ) @@ -3681,6 +3681,8 @@ IntCreatePolyPolygonRgn( int numFullPtBlocks = 0; INT poly, total; + if (mode == 0 || mode > 2) return 0; + if (!(region = REGION_AllocRgnWithHandle(nbpolygons))) return 0; hrgn = region->BaseObject.hHmgr; @@ -3851,139 +3853,4 @@ IntCreatePolyPolygonRgn( return hrgn; } - -HRGN -FASTCALL -GdiCreatePolyPolygonRgn( - CONST PPOINT pt, - CONST PINT PolyCounts, - INT Count, - INT PolyFillMode -) -{ - POINT *Safept; - INT *SafePolyCounts; - INT nPoints, nEmpty, nInvalid, i; - HRGN hRgn; - NTSTATUS Status = STATUS_SUCCESS; - - if (pt == NULL || PolyCounts == NULL || Count == 0 || - (PolyFillMode != WINDING && PolyFillMode != ALTERNATE)) - { - /* Windows doesn't set a last error here */ - return (HRGN)0; - } - - _SEH_TRY - { - ProbeForRead(PolyCounts, Count * sizeof(INT), 1); - /* just probe one point for now, we don't know the length of the array yet */ - ProbeForRead(pt, sizeof(POINT), 1); - } - _SEH_HANDLE - { - Status = _SEH_GetExceptionCode(); - } - _SEH_END; - - if (!NT_SUCCESS(Status)) - { - SetLastNtError(Status); - return (HRGN)0; - } - - if (!(SafePolyCounts = ExAllocatePoolWithTag(PagedPool, Count * sizeof(INT), TAG_REGION))) - { - SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY); - return (HRGN)0; - } - - _SEH_TRY - { - /* pointers were already probed! */ - RtlCopyMemory(SafePolyCounts, - PolyCounts, - Count * sizeof(INT)); - } - _SEH_HANDLE - { - Status = _SEH_GetExceptionCode(); - } - _SEH_END; - - 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 = ExAllocatePoolWithTag(PagedPool, nPoints * sizeof(POINT), TAG_REGION))) - { - ExFreePool(SafePolyCounts); - SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY); - return (HRGN)0; - } - - _SEH_TRY - { - ProbeForRead(pt, nPoints * sizeof(POINT), 1); - /* pointers were already probed! */ - RtlCopyMemory(Safept, - pt, - nPoints * sizeof(POINT)); - } - _SEH_HANDLE - { - Status = _SEH_GetExceptionCode(); - } - _SEH_END; - if (!NT_SUCCESS(Status)) - { - ExFreePool(Safept); - ExFreePool(SafePolyCounts); - SetLastNtError(Status); - return (HRGN)0; - } - - /* now we're ready to calculate the region safely */ - hRgn = IntCreatePolyPolygonRgn(Safept, SafePolyCounts, Count, PolyFillMode); - - ExFreePool(Safept); - ExFreePool(SafePolyCounts); - return hRgn; -} - /* EOF */