mirror of
https://github.com/reactos/reactos.git
synced 2025-08-02 11:57:01 +00:00
- rewrite NtGdiPolyPolyDraw, optimizing it and making it more windows compatible
- Make PolyCounts ULONGs, not DWORDS or INTs. - Remove GdiCreatePolyPolygonRgn and use IntCreatePolyPolygonRgn instead to get rid of code-duplication. - IntGdiPolygon: rename UnsafePoints to Points svn path=/trunk/; revision=36686
This commit is contained in:
parent
8a8e0aaae0
commit
419b09b96a
6 changed files with 142 additions and 309 deletions
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 */
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue