- 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:
Timo Kreuzer 2008-10-07 23:02:41 +00:00
parent 8a8e0aaae0
commit 419b09b96a
6 changed files with 142 additions and 309 deletions

View file

@ -93,7 +93,7 @@ IntGdiPolyBezierTo(DC *dc,
BOOL FASTCALL BOOL FASTCALL
IntGdiPolyPolyline(DC *dc, IntGdiPolyPolyline(DC *dc,
LPPOINT pt, LPPOINT pt,
LPDWORD PolyPoints, PULONG PolyPoints,
DWORD Count); DWORD Count);
BOOL FASTCALL BOOL FASTCALL
@ -125,7 +125,7 @@ IntGdiPolygon(PDC dc,
BOOL FASTCALL BOOL FASTCALL
IntGdiPolyPolygon(DC *dc, IntGdiPolyPolygon(DC *dc,
LPPOINT Points, LPPOINT Points,
LPINT PolyCounts, PULONG PolyCounts,
int Count); int Count);
BOOL FASTCALL IntGdiGradientFill(DC *dc, BOOL FASTCALL IntGdiGradientFill(DC *dc,

View file

@ -43,7 +43,7 @@ VOID FASTCALL IntGdiReleaseVisRgn(PDC);
INT STDCALL IntGdiGetRgnBox(HRGN, LPRECT); INT STDCALL IntGdiGetRgnBox(HRGN, LPRECT);
BOOL FASTCALL IntGdiPaintRgn(PDC, HRGN ); 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 IntGdiCombineRgn(PROSRGNDATA, PROSRGNDATA, PROSRGNDATA, INT);
INT FASTCALL REGION_Complexity(PROSRGNDATA); INT FASTCALL REGION_Complexity(PROSRGNDATA);

View file

@ -51,7 +51,7 @@ BOOL FASTCALL IntDrawRoundRect( PDC dc, INT Left, INT Top, INT Right, INT Bottom
BOOL FASTCALL BOOL FASTCALL
IntGdiPolygon(PDC dc, IntGdiPolygon(PDC dc,
PPOINT UnsafePoints, PPOINT Points,
int Count) int Count)
{ {
BITMAPOBJ *BitmapObj; BITMAPOBJ *BitmapObj;
@ -64,7 +64,7 @@ IntGdiPolygon(PDC dc,
ASSERT(dc); // caller's responsibility to pass a valid dc ASSERT(dc); // caller's responsibility to pass a valid dc
if ( NULL == UnsafePoints || Count < 2 ) if (!Points || Count < 2 )
{ {
SetLastWin32Error(ERROR_INVALID_PARAMETER); SetLastWin32Error(ERROR_INVALID_PARAMETER);
return FALSE; return FALSE;
@ -74,25 +74,25 @@ IntGdiPolygon(PDC dc,
if (!Dc_Attr) Dc_Attr = &dc->Dc_Attr; if (!Dc_Attr) Dc_Attr = &dc->Dc_Attr;
/* Convert to screen coordinates */ /* Convert to screen coordinates */
IntLPtoDP(dc, UnsafePoints, Count); IntLPtoDP(dc, Points, Count);
for (CurrentPoint = 0; CurrentPoint < Count; CurrentPoint++) for (CurrentPoint = 0; CurrentPoint < Count; CurrentPoint++)
{ {
UnsafePoints[CurrentPoint].x += dc->ptlDCOrig.x; Points[CurrentPoint].x += dc->ptlDCOrig.x;
UnsafePoints[CurrentPoint].y += dc->ptlDCOrig.y; Points[CurrentPoint].y += dc->ptlDCOrig.y;
} }
// No need to have path here. // No need to have path here.
{ {
DestRect.left = UnsafePoints[0].x; DestRect.left = Points[0].x;
DestRect.right = UnsafePoints[0].x; DestRect.right = Points[0].x;
DestRect.top = UnsafePoints[0].y; DestRect.top = Points[0].y;
DestRect.bottom = UnsafePoints[0].y; DestRect.bottom = Points[0].y;
for (CurrentPoint = 1; CurrentPoint < Count; ++CurrentPoint) for (CurrentPoint = 1; CurrentPoint < Count; ++CurrentPoint)
{ {
DestRect.left = min(DestRect.left, UnsafePoints[CurrentPoint].x); DestRect.left = min(DestRect.left, Points[CurrentPoint].x);
DestRect.right = max(DestRect.right, UnsafePoints[CurrentPoint].x); DestRect.right = max(DestRect.right, Points[CurrentPoint].x);
DestRect.top = min(DestRect.top, UnsafePoints[CurrentPoint].y); DestRect.top = min(DestRect.top, Points[CurrentPoint].y);
DestRect.bottom = max(DestRect.bottom, UnsafePoints[CurrentPoint].y); DestRect.bottom = max(DestRect.bottom, Points[CurrentPoint].y);
} }
/* Special locking order to avoid lock-ups */ /* Special locking order to avoid lock-ups */
@ -106,7 +106,7 @@ IntGdiPolygon(PDC dc,
if (FillBrushObj && !(FillBrushObj->flAttrs & GDIBRUSH_IS_NULL)) if (FillBrushObj && !(FillBrushObj->flAttrs & GDIBRUSH_IS_NULL))
{ {
IntGdiInitBrushInstance(&FillBrushInst, FillBrushObj, dc->XlateBrush); 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) if (FillBrushObj)
BRUSHOBJ_UnlockBrush(FillBrushObj); BRUSHOBJ_UnlockBrush(FillBrushObj);
@ -122,16 +122,16 @@ IntGdiPolygon(PDC dc,
{ {
// DPRINT1("Polygon Making line from (%d,%d) to (%d,%d)\n", // DPRINT1("Polygon Making line from (%d,%d) to (%d,%d)\n",
// UnsafePoints[0].x, UnsafePoints[0].y, // Points[0].x, Points[0].y,
// UnsafePoints[1].x, UnsafePoints[1].y ); // Points[1].x, Points[1].y );
ret = IntEngLineTo(&BitmapObj->SurfObj, ret = IntEngLineTo(&BitmapObj->SurfObj,
dc->CombinedClip, dc->CombinedClip,
&PenBrushInst.BrushObject, &PenBrushInst.BrushObject,
UnsafePoints[i].x, /* From */ Points[i].x, /* From */
UnsafePoints[i].y, Points[i].y,
UnsafePoints[i+1].x, /* To */ Points[i+1].x, /* To */
UnsafePoints[i+1].y, Points[i+1].y,
&DestRect, &DestRect,
ROP2_TO_MIX(Dc_Attr->jROP2)); /* MIX */ ROP2_TO_MIX(Dc_Attr->jROP2)); /* MIX */
if (!ret) break; if (!ret) break;
@ -142,10 +142,10 @@ IntGdiPolygon(PDC dc,
ret = IntEngLineTo(&BitmapObj->SurfObj, ret = IntEngLineTo(&BitmapObj->SurfObj,
dc->CombinedClip, dc->CombinedClip,
&PenBrushInst.BrushObject, &PenBrushInst.BrushObject,
UnsafePoints[Count-1].x, /* From */ Points[Count-1].x, /* From */
UnsafePoints[Count-1].y, Points[Count-1].y,
UnsafePoints[0].x, /* To */ Points[0].x, /* To */
UnsafePoints[0].y, Points[0].y,
&DestRect, &DestRect,
ROP2_TO_MIX(Dc_Attr->jROP2)); /* MIX */ ROP2_TO_MIX(Dc_Attr->jROP2)); /* MIX */
} }
@ -161,11 +161,11 @@ IntGdiPolygon(PDC dc,
BOOL FASTCALL BOOL FASTCALL
IntGdiPolyPolygon(DC *dc, IntGdiPolyPolygon(DC *dc,
LPPOINT Points, LPPOINT Points,
LPINT PolyCounts, PULONG PolyCounts,
int Count) int Count)
{ {
if (PATH_IsPathOpen(dc->DcLevel)) if (PATH_IsPathOpen(dc->DcLevel))
return PATH_PolyPolygon ( dc, Points, PolyCounts, Count); return PATH_PolyPolygon ( dc, Points, (PINT)PolyCounts, Count);
while (--Count >=0) while (--Count >=0)
{ {
@ -336,185 +336,152 @@ extern BOOL FillPolygon(PDC dc,
ULONG_PTR ULONG_PTR
STDCALL STDCALL
NtGdiPolyPolyDraw( IN HDC hDC, NtGdiPolyPolyDraw( IN HDC hDC,
IN PPOINT Points, IN PPOINT UnsafePoints,
IN PULONG PolyCounts, IN PULONG UnsafeCounts,
IN ULONG Count, IN ULONG Count,
IN INT iFunc ) IN INT iFunc )
{ {
DC *dc; DC *dc;
LPPOINT Safept; PVOID pTemp;
LPINT SafePolyPoints; LPPOINT SafePoints;
PULONG SafeCounts;
NTSTATUS Status = STATUS_SUCCESS; NTSTATUS Status = STATUS_SUCCESS;
BOOL Ret = TRUE; 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, /* Windows doesn't set last error */
(CONST PINT) PolyCounts,
Count,
(INT) hDC);
}
dc = DC_LockDc(hDC);
if (!dc)
{
SetLastWin32Error(ERROR_INVALID_HANDLE);
return FALSE; return FALSE;
} }
if (dc->DC_Type == DC_TYPE_INFO)
_SEH_TRY
{ {
DC_UnlockDc(dc); ProbeForRead(UnsafePoints, Count * sizeof(POINT), 1);
/* Yes, Windows really returns TRUE in this case */ ProbeForRead(UnsafeCounts, Count * sizeof(ULONG), 1);
return TRUE;
}
if (Count > 0) /* Count points and validate poligons */
{
_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;
for (i = 0; i < Count; i++) for (i = 0; i < Count; i++)
{ {
if (SafePolyPoints[i] == 0) if (UnsafeCounts[i] < 2)
{
nEmpty++;
}
if (SafePolyPoints[i] == 1)
{ {
nInvalid++; nInvalid++;
} }
nPoints += SafePolyPoints[i]; nPoints += UnsafeCounts[i];
} nMaxPoints = max(nMaxPoints, UnsafeCounts[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;
} }
} }
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); SetLastWin32Error(ERROR_INVALID_PARAMETER);
return FALSE; 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) switch (iFunc)
{ {
case GdiPolyPolygon: case GdiPolyPolygon:
Ret = IntGdiPolyPolygon(dc, Safept, SafePolyPoints, Count); Ret = IntGdiPolyPolygon(dc, SafePoints, SafeCounts, Count);
break; break;
case GdiPolyPolyLine: case GdiPolyPolyLine:
Ret = IntGdiPolyPolyline(dc, Safept, (LPDWORD) SafePolyPoints, Count); Ret = IntGdiPolyPolyline(dc, SafePoints, SafeCounts, Count);
break; break;
case GdiPolyBezier: case GdiPolyBezier:
Ret = IntGdiPolyBezier(dc, Safept, *PolyCounts); Ret = IntGdiPolyBezier(dc, SafePoints, *SafeCounts);
break; break;
case GdiPolyLineTo: case GdiPolyLineTo:
Ret = IntGdiPolylineTo(dc, Safept, *PolyCounts); Ret = IntGdiPolylineTo(dc, SafePoints, *SafeCounts);
break; break;
case GdiPolyBezierTo: case GdiPolyBezierTo:
Ret = IntGdiPolyBezierTo(dc, Safept, *PolyCounts); Ret = IntGdiPolyBezierTo(dc, SafePoints, *SafeCounts);
break; break;
default: default:
SetLastWin32Error(ERROR_INVALID_PARAMETER); SetLastWin32Error(ERROR_INVALID_PARAMETER);
Ret = FALSE; 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;
} }

View file

@ -350,12 +350,12 @@ IntGdiPolylineTo(DC *dc,
BOOL FASTCALL BOOL FASTCALL
IntGdiPolyPolyline(DC *dc, IntGdiPolyPolyline(DC *dc,
LPPOINT pt, LPPOINT pt,
LPDWORD PolyPoints, PULONG PolyPoints,
DWORD Count) DWORD Count)
{ {
int i; int i;
LPPOINT pts; LPPOINT pts;
LPDWORD pc; PULONG pc;
BOOL ret = FALSE; // default to failure BOOL ret = FALSE; // default to failure
pts = pt; pts = pt;
pc = PolyPoints; pc = PolyPoints;

View file

@ -1028,7 +1028,6 @@ PATH_FlattenPath(PPATH pPath)
} }
HRGN FASTCALL IntCreatePolyPolygonRgn(POINT *Pts, INT *Count, INT nbpolygons,INT mode);
/* PATH_PathToRegion /* PATH_PathToRegion
* *
* Creates a region from the specified path using the specified polygon * Creates a region from the specified path using the specified polygon
@ -1042,7 +1041,7 @@ FASTCALL
PATH_PathToRegion ( PPATH pPath, INT nPolyFillMode, HRGN *pHrgn ) PATH_PathToRegion ( PPATH pPath, INT nPolyFillMode, HRGN *pHrgn )
{ {
int numStrokes, iStroke, i; int numStrokes, iStroke, i;
INT *pNumPointsInStroke; PULONG pNumPointsInStroke;
HRGN hrgn = 0; HRGN hrgn = 0;
ASSERT(pPath!=NULL); ASSERT(pPath!=NULL);
@ -1060,7 +1059,7 @@ PATH_PathToRegion ( PPATH pPath, INT nPolyFillMode, HRGN *pHrgn )
numStrokes++; numStrokes++;
/* Allocate memory for number-of-points-in-stroke array */ /* 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) if(!pNumPointsInStroke)
{ {
SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY); SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);

View file

@ -3560,7 +3560,7 @@ REGION_PtsToRegion(
*/ */
static void FASTCALL static void FASTCALL
REGION_CreateETandAET( REGION_CreateETandAET(
const INT *Count, const ULONG *Count,
INT nbpolygons, INT nbpolygons,
const POINT *pts, const POINT *pts,
EdgeTable *ET, EdgeTable *ET,
@ -3657,7 +3657,7 @@ REGION_CreateETandAET(
HRGN FASTCALL HRGN FASTCALL
IntCreatePolyPolygonRgn( IntCreatePolyPolygonRgn(
POINT *Pts, POINT *Pts,
INT *Count, PULONG Count,
INT nbpolygons, INT nbpolygons,
INT mode INT mode
) )
@ -3681,6 +3681,8 @@ IntCreatePolyPolygonRgn(
int numFullPtBlocks = 0; int numFullPtBlocks = 0;
INT poly, total; INT poly, total;
if (mode == 0 || mode > 2) return 0;
if (!(region = REGION_AllocRgnWithHandle(nbpolygons))) if (!(region = REGION_AllocRgnWithHandle(nbpolygons)))
return 0; return 0;
hrgn = region->BaseObject.hHmgr; hrgn = region->BaseObject.hHmgr;
@ -3851,139 +3853,4 @@ IntCreatePolyPolygonRgn(
return hrgn; 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 */ /* EOF */