Author: tkreuzer
Date: Tue Oct 7 18:02:41 2008
New Revision: 36686
URL:
http://svn.reactos.org/svn/reactos?rev=36686&view=rev
Log:
- 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
Modified:
trunk/reactos/subsystems/win32/win32k/include/intgdi.h
trunk/reactos/subsystems/win32/win32k/include/region.h
trunk/reactos/subsystems/win32/win32k/objects/fillshap.c
trunk/reactos/subsystems/win32/win32k/objects/line.c
trunk/reactos/subsystems/win32/win32k/objects/path.c
trunk/reactos/subsystems/win32/win32k/objects/region.c
Modified: trunk/reactos/subsystems/win32/win32k/include/intgdi.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/in…
==============================================================================
--- trunk/reactos/subsystems/win32/win32k/include/intgdi.h [iso-8859-1] (original)
+++ trunk/reactos/subsystems/win32/win32k/include/intgdi.h [iso-8859-1] Tue Oct 7
18:02:41 2008
@@ -93,7 +93,7 @@
BOOL FASTCALL
IntGdiPolyPolyline(DC *dc,
LPPOINT pt,
- LPDWORD PolyPoints,
+ PULONG PolyPoints,
DWORD Count);
BOOL FASTCALL
@@ -125,7 +125,7 @@
BOOL FASTCALL
IntGdiPolyPolygon(DC *dc,
LPPOINT Points,
- LPINT PolyCounts,
+ PULONG PolyCounts,
int Count);
BOOL FASTCALL IntGdiGradientFill(DC *dc,
Modified: trunk/reactos/subsystems/win32/win32k/include/region.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/in…
==============================================================================
--- trunk/reactos/subsystems/win32/win32k/include/region.h [iso-8859-1] (original)
+++ trunk/reactos/subsystems/win32/win32k/include/region.h [iso-8859-1] Tue Oct 7
18:02:41 2008
@@ -43,7 +43,7 @@
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);
Modified: trunk/reactos/subsystems/win32/win32k/objects/fillshap.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/ob…
==============================================================================
--- trunk/reactos/subsystems/win32/win32k/objects/fillshap.c [iso-8859-1] (original)
+++ trunk/reactos/subsystems/win32/win32k/objects/fillshap.c [iso-8859-1] Tue Oct 7
18:02:41 2008
@@ -51,7 +51,7 @@
BOOL FASTCALL
IntGdiPolygon(PDC dc,
- PPOINT UnsafePoints,
+ PPOINT Points,
int Count)
{
BITMAPOBJ *BitmapObj;
@@ -64,7 +64,7 @@
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 @@
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 @@
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 @@
{
// 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 @@
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 @@
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 @@
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;
-
- if (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);
- return FALSE;
- }
- if (dc->DC_Type == DC_TYPE_INFO)
- {
- DC_UnlockDc(dc);
- /* Yes, Windows really returns TRUE in this case */
- return TRUE;
- }
-
- 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;
+ INT nPoints = 0, nMaxPoints = 0, nInvalid = 0, i;
+
+ if (!UnsafePoints || !UnsafeCounts ||
+ Count == 0 || iFunc == 0 || iFunc > GdiPolyPolyRgn)
+ {
+ /* Windows doesn't set last error */
+ return FALSE;
+ }
+
+ _SEH_TRY
+ {
+ ProbeForRead(UnsafePoints, Count * sizeof(POINT), 1);
+ ProbeForRead(UnsafeCounts, Count * sizeof(ULONG), 1);
+
+ /* 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];
+ 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
+ {
+ 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);
- SetLastWin32Error(ERROR_INVALID_PARAMETER);
- return FALSE;
- }
-
+ 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);
+
+ /* Cleanup and return */
DC_UnlockDc(dc);
-
- return (ULONG_PTR) Ret;
+ ExFreePool(pTemp);
+
+ return (ULONG_PTR)Ret;
}
Modified: trunk/reactos/subsystems/win32/win32k/objects/line.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/ob…
==============================================================================
--- trunk/reactos/subsystems/win32/win32k/objects/line.c [iso-8859-1] (original)
+++ trunk/reactos/subsystems/win32/win32k/objects/line.c [iso-8859-1] Tue Oct 7 18:02:41
2008
@@ -350,12 +350,12 @@
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;
Modified: trunk/reactos/subsystems/win32/win32k/objects/path.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/ob…
==============================================================================
--- trunk/reactos/subsystems/win32/win32k/objects/path.c [iso-8859-1] (original)
+++ trunk/reactos/subsystems/win32/win32k/objects/path.c [iso-8859-1] Tue Oct 7 18:02:41
2008
@@ -1028,7 +1028,6 @@
}
-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 @@
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 @@
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);
Modified: trunk/reactos/subsystems/win32/win32k/objects/region.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/ob…
==============================================================================
--- trunk/reactos/subsystems/win32/win32k/objects/region.c [iso-8859-1] (original)
+++ trunk/reactos/subsystems/win32/win32k/objects/region.c [iso-8859-1] Tue Oct 7
18:02:41 2008
@@ -3560,7 +3560,7 @@
*/
static void FASTCALL
REGION_CreateETandAET(
- const INT *Count,
+ const ULONG *Count,
INT nbpolygons,
const POINT *pts,
EdgeTable *ET,
@@ -3657,7 +3657,7 @@
HRGN FASTCALL
IntCreatePolyPolygonRgn(
POINT *Pts,
- INT *Count,
+ PULONG Count,
INT nbpolygons,
INT mode
)
@@ -3680,6 +3680,8 @@
POINTBLOCK *tmpPtBlock;
int numFullPtBlocks = 0;
INT poly, total;
+
+ if (mode == 0 || mode > 2) return 0;
if (!(region = REGION_AllocRgnWithHandle(nbpolygons)))
return 0;
@@ -3851,139 +3853,4 @@
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 */