Author: jimtabor
Date: Mon Jan 4 02:36:24 2010
New Revision: 44923
URL:
http://svn.reactos.org/svn/reactos?rev=44923&view=rev
Log:
- Another attempt to fix RGNOBJAPI_Un/Lock SEH issue. Resort code.
Modified:
trunk/reactos/subsystems/win32/win32k/objects/region.c
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] Mon Jan 4
02:36:24 2010
@@ -2084,7 +2084,8 @@
INT Index;
PGDI_TABLE_ENTRY Entry;
PROSRGNDATA pRgn;
- PRGN_ATTR pRgn_Attr;
+ PRGN_ATTR pRgn_Attr;
+ BOOL Hit = FALSE;
pRgn = REGION_LockRgn(hRgn);
@@ -2124,6 +2125,7 @@
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
+ Hit = TRUE;
}
_SEH2_END;
@@ -2146,6 +2148,7 @@
INT Index;
PGDI_TABLE_ENTRY Entry;
PRGN_ATTR pRgn_Attr;
+ BOOL Hit = FALSE;
if (pRgn)
{
@@ -2172,6 +2175,7 @@
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
+ Hit = TRUE;
}
_SEH2_END;
}
@@ -2315,65 +2319,6 @@
return result;
}
-
-// NtGdi Exported Functions
-INT
-APIENTRY
-NtGdiCombineRgn(HRGN hDest,
- HRGN hSrc1,
- HRGN hSrc2,
- INT CombineMode)
-{
- INT result = ERROR;
- PROSRGNDATA destRgn, src1Rgn, src2Rgn = NULL;
-
- if ( CombineMode > RGN_COPY && CombineMode < RGN_AND)
- {
- SetLastWin32Error(ERROR_INVALID_PARAMETER);
- return ERROR;
- }
-
- destRgn = RGNOBJAPI_Lock(hDest, NULL);
- if (!destRgn)
- {
- SetLastWin32Error(ERROR_INVALID_HANDLE);
- return ERROR;
- }
-
- src1Rgn = RGNOBJAPI_Lock(hSrc1, NULL);
- if (!src1Rgn)
- {
- RGNOBJAPI_Unlock(destRgn);
- SetLastWin32Error(ERROR_INVALID_HANDLE);
- return ERROR;
- }
-
- if (hSrc2)
- src2Rgn = RGNOBJAPI_Lock(hSrc2, NULL);
-
- result = IntGdiCombineRgn( destRgn, src1Rgn, src2Rgn, CombineMode);
-
- if (src2Rgn)
- RGNOBJAPI_Unlock(src2Rgn);
- RGNOBJAPI_Unlock(src1Rgn);
- RGNOBJAPI_Unlock(destRgn);
-
- return result;
-}
-
-HRGN
-APIENTRY
-NtGdiCreateEllipticRgn(
- INT Left,
- INT Top,
- INT Right,
- INT Bottom
-)
-{
- return NtGdiCreateRoundRectRgn(Left, Top, Right, Bottom,
- Right - Left, Bottom - Top);
-}
-
PROSRGNDATA
FASTCALL
IntGdiCreateRectRgn(INT LeftRect, INT TopRect, INT RightRect, INT BottomRect)
@@ -2388,362 +2333,6 @@
pRgn = GDIOBJ_ShareLockObj(pRgn->BaseObject.hHmgr, GDI_OBJECT_TYPE_REGION);
return pRgn;
-}
-
-
-HRGN APIENTRY
-NtGdiCreateRectRgn(INT LeftRect, INT TopRect, INT RightRect, INT BottomRect)
-{
- PROSRGNDATA pRgn;
- HRGN hRgn;
-
- /* Allocate region data structure with space for 1 RECTL */
- if (!(pRgn = REGION_AllocRgnWithHandle(1)))
- {
- SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
- return NULL;
- }
- hRgn = pRgn->BaseObject.hHmgr;
-
- REGION_SetRectRgn(pRgn, LeftRect, TopRect, RightRect, BottomRect);
- RGNOBJAPI_Unlock(pRgn);
-
- return hRgn;
-}
-
-
-HRGN
-APIENTRY
-NtGdiCreateRoundRectRgn(
- INT left,
- INT top,
- INT right,
- INT bottom,
- INT ellipse_width,
- INT ellipse_height
-)
-{
- PROSRGNDATA obj;
- HRGN hrgn;
- int asq, bsq, d, xd, yd;
- RECTL rect;
-
- /* Make the dimensions sensible */
-
- if (left > right)
- {
- INT tmp = left;
- left = right;
- right = tmp;
- }
- if (top > bottom)
- {
- INT tmp = top;
- top = bottom;
- bottom = tmp;
- }
-
- ellipse_width = abs(ellipse_width);
- ellipse_height = abs(ellipse_height);
-
- /* Check parameters */
-
- if (ellipse_width > right-left) ellipse_width = right-left;
- if (ellipse_height > bottom-top) ellipse_height = bottom-top;
-
- /* Check if we can do a normal rectangle instead */
-
- if ((ellipse_width < 2) || (ellipse_height < 2))
- return NtGdiCreateRectRgn(left, top, right, bottom);
-
- /* Create region */
-
- d = (ellipse_height < 128) ? ((3 * ellipse_height) >> 2) : 64;
- if (!(obj = REGION_AllocRgnWithHandle(d))) return 0;
- hrgn = obj->BaseObject.hHmgr;
-
- /* Ellipse algorithm, based on an article by K. Porter */
- /* in DDJ Graphics Programming Column, 8/89 */
-
- asq = ellipse_width * ellipse_width / 4; /* a^2 */
- bsq = ellipse_height * ellipse_height / 4; /* b^2 */
- d = bsq - asq * ellipse_height / 2 + asq / 4; /* b^2 - a^2b + a^2/4 */
- xd = 0;
- yd = asq * ellipse_height; /* 2a^2b */
-
- rect.left = left + ellipse_width / 2;
- rect.right = right - ellipse_width / 2;
-
- /* Loop to draw first half of quadrant */
-
- while (xd < yd)
- {
- if (d > 0) /* if nearest pixel is toward the center */
- {
- /* move toward center */
- rect.top = top++;
- rect.bottom = rect.top + 1;
- REGION_UnionRectWithRgn(obj, &rect);
- rect.top = --bottom;
- rect.bottom = rect.top + 1;
- REGION_UnionRectWithRgn(obj, &rect);
- yd -= 2*asq;
- d -= yd;
- }
- rect.left--; /* next horiz point */
- rect.right++;
- xd += 2*bsq;
- d += bsq + xd;
- }
- /* Loop to draw second half of quadrant */
-
- d += (3 * (asq-bsq) / 2 - (xd+yd)) / 2;
- while (yd >= 0)
- {
- /* next vertical point */
- rect.top = top++;
- rect.bottom = rect.top + 1;
- REGION_UnionRectWithRgn(obj, &rect);
- rect.top = --bottom;
- rect.bottom = rect.top + 1;
- REGION_UnionRectWithRgn(obj, &rect);
- if (d < 0) /* if nearest pixel is outside ellipse */
- {
- rect.left--; /* move away from center */
- rect.right++;
- xd += 2*bsq;
- d += xd;
- }
- yd -= 2*asq;
- d += asq - yd;
- }
- /* Add the inside rectangle */
-
- if (top <= bottom)
- {
- rect.top = top;
- rect.bottom = bottom;
- REGION_UnionRectWithRgn(obj, &rect);
- }
-
- RGNOBJAPI_Unlock(obj);
- return hrgn;
-}
-
-BOOL
-APIENTRY
-NtGdiEqualRgn(
- HRGN hSrcRgn1,
- HRGN hSrcRgn2
-)
-{
- PROSRGNDATA rgn1, rgn2;
- PRECTL tRect1, tRect2;
- ULONG i;
- BOOL bRet = FALSE;
-
- if ( !(rgn1 = RGNOBJAPI_Lock(hSrcRgn1, NULL)) )
- return ERROR;
-
- if ( !(rgn2 = RGNOBJAPI_Lock(hSrcRgn2, NULL)) )
- {
- RGNOBJAPI_Unlock(rgn1);
- return ERROR;
- }
-
- if (rgn1->rdh.nCount != rgn2->rdh.nCount ||
- rgn1->rdh.nCount == 0 ||
- rgn1->rdh.rcBound.left != rgn2->rdh.rcBound.left ||
- rgn1->rdh.rcBound.right != rgn2->rdh.rcBound.right ||
- rgn1->rdh.rcBound.top != rgn2->rdh.rcBound.top ||
- rgn1->rdh.rcBound.bottom != rgn2->rdh.rcBound.bottom)
- goto exit;
-
- tRect1 = rgn1->Buffer;
- tRect2 = rgn2->Buffer;
-
- if (!tRect1 || !tRect2)
- goto exit;
-
- for (i=0; i < rgn1->rdh.nCount; i++)
- {
- if (tRect1[i].left != tRect2[i].left ||
- tRect1[i].right != tRect2[i].right ||
- tRect1[i].top != tRect2[i].top ||
- tRect1[i].bottom != tRect2[i].bottom)
- goto exit;
- }
- bRet = TRUE;
-
-exit:
- RGNOBJAPI_Unlock(rgn1);
- RGNOBJAPI_Unlock(rgn2);
- return bRet;
-}
-
-HRGN
-APIENTRY
-NtGdiExtCreateRegion(
- OPTIONAL LPXFORM Xform,
- DWORD Count,
- LPRGNDATA RgnData
-)
-{
- HRGN hRgn;
- PROSRGNDATA Region;
- DWORD nCount = 0;
- DWORD iType = 0;
- DWORD dwSize = 0;
- NTSTATUS Status = STATUS_SUCCESS;
- MATRIX matrix;
-
- DPRINT("NtGdiExtCreateRegion\n");
- _SEH2_TRY
- {
- ProbeForRead(RgnData, Count, 1);
- nCount = RgnData->rdh.nCount;
- iType = RgnData->rdh.iType;
- dwSize = RgnData->rdh.dwSize;
- }
- _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
- {
- Status = _SEH2_GetExceptionCode();
- }
- _SEH2_END;
- if (!NT_SUCCESS(Status))
- {
- SetLastNtError(Status);
- return NULL;
- }
-
- /* Check parameters, but don't set last error here */
- if (Count < sizeof(RGNDATAHEADER) + nCount * sizeof(RECT) ||
- iType != RDH_RECTANGLES ||
- dwSize != sizeof(RGNDATAHEADER))
- {
- return NULL;
- }
-
- Region = REGION_AllocRgnWithHandle(nCount);
-
- if (Region == NULL)
- {
- SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
- return FALSE;
- }
- hRgn = Region->BaseObject.hHmgr;
-
- _SEH2_TRY
- {
- if (Xform)
- {
- ULONG ret;
-
- /* Init the XFORMOBJ from the Xform struct */
- Status = STATUS_INVALID_PARAMETER;
- ret = XFORMOBJ_iSetXform((XFORMOBJ*)&matrix, (XFORML*)Xform);
-
- /* Check for error, also no scale and shear allowed */
- if (ret != DDI_ERROR && ret != GX_GENERAL)
- {
- /* Apply the coordinate transformation on the rects */
- if (XFORMOBJ_bApplyXform((XFORMOBJ*)&matrix,
- XF_LTOL,
- nCount * 2,
- RgnData->Buffer,
- Region->Buffer))
- {
- Status = STATUS_SUCCESS;
- }
- }
- }
- else
- {
- /* Copy rect coordinates */
- RtlCopyMemory(Region->Buffer,
- RgnData->Buffer,
- nCount * sizeof(RECT));
- }
- }
- _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
- {
- Status = _SEH2_GetExceptionCode();
- }
- _SEH2_END;
- if (!NT_SUCCESS(Status))
- {
- SetLastWin32Error(ERROR_INVALID_PARAMETER);
- RGNOBJAPI_Unlock(Region);
- GreDeleteObject(hRgn);
- return NULL;
- }
-
- RGNOBJAPI_Unlock(Region);
-
- return hRgn;
-}
-
-BOOL
-APIENTRY
-NtGdiFillRgn(
- HDC hDC,
- HRGN hRgn,
- HBRUSH hBrush
-)
-{
- HBRUSH oldhBrush;
- PROSRGNDATA rgn;
- PRECTL r;
-
- if (NULL == (rgn = RGNOBJAPI_Lock(hRgn, NULL)))
- {
- return FALSE;
- }
-
- if (NULL == (oldhBrush = NtGdiSelectBrush(hDC, hBrush)))
- {
- RGNOBJAPI_Unlock(rgn);
- return FALSE;
- }
-
- for (r = rgn->Buffer; r < rgn->Buffer + rgn->rdh.nCount; r++)
- {
- NtGdiPatBlt(hDC, r->left, r->top, r->right - r->left, r->bottom -
r->top, PATCOPY);
- }
-
- RGNOBJAPI_Unlock(rgn);
- NtGdiSelectBrush(hDC, oldhBrush);
-
- return TRUE;
-}
-
-BOOL
-APIENTRY
-NtGdiFrameRgn(
- HDC hDC,
- HRGN hRgn,
- HBRUSH hBrush,
- INT Width,
- INT Height
-)
-{
- HRGN FrameRgn;
- BOOL Ret;
-
- if (!(FrameRgn = NtGdiCreateRectRgn(0, 0, 0, 0)))
- {
- return FALSE;
- }
- if (!REGION_CreateFrameRgn(FrameRgn, hRgn, Width, Height))
- {
- GreDeleteObject(FrameRgn);
- return FALSE;
- }
-
- Ret = NtGdiFillRgn(hDC, FrameRgn, hBrush);
-
- GreDeleteObject(FrameRgn);
- return Ret;
}
INT FASTCALL
@@ -2764,85 +2353,6 @@
return 0; //if invalid region return zero
}
-
-/* See wine, msdn, osr and Feng Yuan - Windows Graphics Programming Win32 Gdi And
Directdraw
-
- 1st:
http://www.codeproject.com/gdi/cliprgnguide.asp is wrong!
-
- The intersection of the clip with the meta region is not Rao it's API!
- Go back and read 7.2 Clipping pages 418-19:
- Rao = API & Vis:
- 1) The Rao region is the intersection of the API region and the system region,
- named after the Microsoft engineer who initially proposed it.
- 2) The Rao region can be calculated from the API region and the system region.
-
- API:
- API region is the intersection of the meta region and the clipping region,
- clearly named after the fact that it is controlled by GDI API calls.
-*/
-INT APIENTRY
-NtGdiGetRandomRgn(
- HDC hDC,
- HRGN hDest,
- INT iCode
-)
-{
- INT ret = 0;
- PDC pDC;
- HRGN hSrc = NULL;
- POINT org;
-
- pDC = DC_LockDc(hDC);
- if (pDC == NULL)
- {
- SetLastWin32Error(ERROR_INVALID_HANDLE);
- return -1;
- }
-
- switch (iCode)
- {
- case CLIPRGN:
- hSrc = pDC->rosdc.hClipRgn;
-// if (pDC->dclevel.prgnClip) hSrc =
((PROSRGNDATA)pDC->dclevel.prgnClip)->BaseObject.hHmgr;
- break;
- case METARGN:
- if (pDC->dclevel.prgnMeta) hSrc =
((PROSRGNDATA)pDC->dclevel.prgnMeta)->BaseObject.hHmgr;
- break;
- case APIRGN:
- hSrc = pDC->rosdc.hClipRgn;
-// if (pDC->prgnAPI) hSrc =
((PROSRGNDATA)pDC->prgnAPI)->BaseObject.hHmgr;
-// else if (pDC->dclevel.prgnClip) hSrc =
((PROSRGNDATA)pDC->dclevel.prgnClip)->BaseObject.hHmgr;
-// else if (pDC->dclevel.prgnMeta) hSrc =
((PROSRGNDATA)pDC->dclevel.prgnMeta)->BaseObject.hHmgr;
- break;
- case SYSRGN:
- hSrc = pDC->rosdc.hVisRgn;
-// if (pDC->prgnVis) hSrc =
((PROSRGNDATA)pDC->prgnVis)->BaseObject.hHmgr;
- break;
- default:
- hSrc = 0;
- }
- if (hSrc)
- {
- if (NtGdiCombineRgn(hDest, hSrc, 0, RGN_COPY) == ERROR)
- {
- ret = -1;
- }
- else
- {
- ret = 1;
- }
- }
- if (iCode == SYSRGN)
- {
- IntGdiGetDCOrg(pDC, &org);
- NtGdiOffsetRgn(hDest, org.x, org.y );
- }
-
- DC_UnlockDc(pDC);
-
- return ret;
-}
-
INT APIENTRY
IntGdiGetRgnBox(
HRGN hRgn,
@@ -2860,129 +2370,6 @@
ret = REGION_GetRgnBox(Rgn, pRect);
RGNOBJAPI_Unlock(Rgn);
- return ret;
-}
-
-
-INT APIENTRY
-NtGdiGetRgnBox(
- HRGN hRgn,
- PRECTL pRect
-)
-{
- PROSRGNDATA Rgn;
- RECTL SafeRect;
- DWORD ret;
- NTSTATUS Status = STATUS_SUCCESS;
-
- if (!(Rgn = RGNOBJAPI_Lock(hRgn, NULL)))
- {
- return ERROR;
- }
-
- ret = REGION_GetRgnBox(Rgn, &SafeRect);
- RGNOBJAPI_Unlock(Rgn);
- if (ERROR == ret)
- {
- return ret;
- }
-
- _SEH2_TRY
- {
- ProbeForWrite(pRect, sizeof(RECT), 1);
- *pRect = SafeRect;
- }
- _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
- {
- Status = _SEH2_GetExceptionCode();
- }
- _SEH2_END;
- if (!NT_SUCCESS(Status))
- {
- return ERROR;
- }
-
- return ret;
-}
-
-BOOL
-APIENTRY
-NtGdiInvertRgn(
- HDC hDC,
- HRGN hRgn
-)
-{
- PROSRGNDATA RgnData;
- ULONG i;
- PRECTL rc;
-
- if (!(RgnData = RGNOBJAPI_Lock(hRgn, NULL)))
- {
- SetLastWin32Error(ERROR_INVALID_HANDLE);
- return FALSE;
- }
-
- rc = RgnData->Buffer;
- for (i = 0; i < RgnData->rdh.nCount; i++)
- {
-
- if (!NtGdiPatBlt(hDC, rc->left, rc->top, rc->right - rc->left,
rc->bottom - rc->top, DSTINVERT))
- {
- RGNOBJAPI_Unlock(RgnData);
- return FALSE;
- }
- rc++;
- }
-
- RGNOBJAPI_Unlock(RgnData);
- return TRUE;
-}
-
-INT
-APIENTRY
-NtGdiOffsetRgn(
- HRGN hRgn,
- INT XOffset,
- INT YOffset
-)
-{
- PROSRGNDATA rgn = RGNOBJAPI_Lock(hRgn, NULL);
- INT ret;
-
- DPRINT("NtGdiOffsetRgn: hRgn %d Xoffs %d Yoffs %d rgn %x\n", hRgn, XOffset,
YOffset, rgn );
-
- if (!rgn)
- {
- DPRINT("NtGdiOffsetRgn: hRgn error\n");
- return ERROR;
- }
-
- if (XOffset || YOffset)
- {
- int nbox = rgn->rdh.nCount;
- PRECTL pbox = rgn->Buffer;
-
- if (nbox && pbox)
- {
- while (nbox--)
- {
- pbox->left += XOffset;
- pbox->right += XOffset;
- pbox->top += YOffset;
- pbox->bottom += YOffset;
- pbox++;
- }
- if (rgn->Buffer != &rgn->rdh.rcBound)
- {
- rgn->rdh.rcBound.left += XOffset;
- rgn->rdh.rcBound.right += XOffset;
- rgn->rdh.rcBound.top += YOffset;
- rgn->rdh.rcBound.bottom += YOffset;
- }
- }
- }
- ret = REGION_Complexity(rgn);
- RGNOBJAPI_Unlock(rgn);
return ret;
}
@@ -3046,38 +2433,6 @@
// Fill the region
return TRUE;
-}
-
-BOOL
-APIENTRY
-NtGdiPtInRegion(
- HRGN hRgn,
- INT X,
- INT Y
-)
-{
- PROSRGNDATA rgn;
- ULONG i;
- PRECTL r;
-
- if (!(rgn = RGNOBJAPI_Lock(hRgn, NULL) ) )
- return FALSE;
-
- if (rgn->rdh.nCount > 0 && INRECT(rgn->rdh.rcBound, X, Y))
- {
- r = rgn->Buffer;
- for (i = 0; i < rgn->rdh.nCount; i++)
- {
- if (INRECT(*r, X, Y))
- {
- RGNOBJAPI_Unlock(rgn);
- return TRUE;
- }
- r++;
- }
- }
- RGNOBJAPI_Unlock(rgn);
- return FALSE;
}
BOOL
@@ -3130,47 +2485,6 @@
}
}
return FALSE;
-}
-
-BOOL
-APIENTRY
-NtGdiRectInRegion(
- HRGN hRgn,
- LPRECTL unsaferc
-)
-{
- PROSRGNDATA Rgn;
- RECTL rc = {0};
- BOOL Ret;
- NTSTATUS Status = STATUS_SUCCESS;
-
- if (!(Rgn = RGNOBJAPI_Lock(hRgn, NULL)))
- {
- return ERROR;
- }
-
- _SEH2_TRY
- {
- ProbeForRead(unsaferc, sizeof(RECT), 1);
- rc = *unsaferc;
- }
- _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
- {
- Status = _SEH2_GetExceptionCode();
- }
- _SEH2_END;
-
- if (!NT_SUCCESS(Status))
- {
- RGNOBJAPI_Unlock(Rgn);
- SetLastNtError(Status);
- DPRINT1("NtGdiRectInRegion: bogus rc\n");
- return ERROR;
- }
-
- Ret = REGION_RectInRegion(Rgn, &rc);
- RGNOBJAPI_Unlock(Rgn);
- return Ret;
}
VOID
@@ -3210,128 +2524,11 @@
rgn->rdh.iType = RDH_RECTANGLES;
}
else
+ {
+ DPRINT1("SetRectRgn NULL Count: %d \n", rgn->rdh.nCount);
EMPTY_REGION(rgn);
-}
-
-BOOL
-APIENTRY
-NtGdiSetRectRgn(
- HRGN hRgn,
- INT LeftRect,
- INT TopRect,
- INT RightRect,
- INT BottomRect
-)
-{
- PROSRGNDATA rgn;
-
- if ( !(rgn = RGNOBJAPI_Lock(hRgn, NULL)) )
- {
- return 0; //per documentation
- }
-
- REGION_SetRectRgn(rgn, LeftRect, TopRect, RightRect, BottomRect);
-
- RGNOBJAPI_Unlock(rgn);
- return TRUE;
-}
-
-HRGN APIENTRY
-NtGdiUnionRectWithRgn(
- HRGN hDest,
- const RECTL *UnsafeRect
-)
-{
- RECTL SafeRect = {0};
- PROSRGNDATA Rgn;
- NTSTATUS Status = STATUS_SUCCESS;
-
- if (!(Rgn = RGNOBJAPI_Lock(hDest, NULL)))
- {
- SetLastWin32Error(ERROR_INVALID_HANDLE);
- return NULL;
- }
-
- _SEH2_TRY
- {
- ProbeForRead(UnsafeRect, sizeof(RECT), 1);
- SafeRect = *UnsafeRect;
- }
- _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
- {
- Status = _SEH2_GetExceptionCode();
- }
- _SEH2_END;
-
- if (! NT_SUCCESS(Status))
- {
- RGNOBJAPI_Unlock(Rgn);
- SetLastNtError(Status);
- return NULL;
- }
-
- REGION_UnionRectWithRgn(Rgn, &SafeRect);
- RGNOBJAPI_Unlock(Rgn);
- return hDest;
-}
-
-/*!
- * MSDN: GetRegionData, Return Values:
- *
- * "If the function succeeds and dwCount specifies an adequate number of bytes,
- * the return value is always dwCount. If dwCount is too small or the function
- * fails, the return value is 0. If lpRgnData is NULL, the return value is the
- * required number of bytes.
- *
- * If the function fails, the return value is zero."
- */
-DWORD APIENTRY
-NtGdiGetRegionData(
- HRGN hrgn,
- DWORD count,
- LPRGNDATA rgndata
-)
-{
- DWORD size;
- PROSRGNDATA obj = RGNOBJAPI_Lock(hrgn, NULL);
- NTSTATUS Status = STATUS_SUCCESS;
-
- if (!obj)
- return 0;
-
- size = obj->rdh.nCount * sizeof(RECT);
- if (count < (size + sizeof(RGNDATAHEADER)) || rgndata == NULL)
- {
- RGNOBJAPI_Unlock(obj);
- if (rgndata) /* buffer is too small, signal it by return 0 */
- return 0;
- else /* user requested buffer size with rgndata NULL */
- return size + sizeof(RGNDATAHEADER);
- }
-
- _SEH2_TRY
- {
- ProbeForWrite(rgndata, count, 1);
- RtlCopyMemory(rgndata, &obj->rdh, sizeof(RGNDATAHEADER));
- RtlCopyMemory(rgndata->Buffer, obj->Buffer, size);
- }
- _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
- {
- Status = _SEH2_GetExceptionCode();
- }
- _SEH2_END;
-
- if (!NT_SUCCESS(Status))
- {
- SetLastNtError(Status);
- RGNOBJAPI_Unlock(obj);
- return 0;
- }
-
- RGNOBJAPI_Unlock(obj);
- return size + sizeof(RGNDATAHEADER);
-}
-
+ }
+}
/***********************************************************************
* REGION_InsertEdgeInET
@@ -3967,4 +3164,811 @@
return hrgn;
}
+//
+// NtGdi Exported Functions
+//
+INT
+APIENTRY
+NtGdiCombineRgn(HRGN hDest,
+ HRGN hSrc1,
+ HRGN hSrc2,
+ INT CombineMode)
+{
+ INT result = ERROR;
+ PROSRGNDATA destRgn, src1Rgn, src2Rgn = NULL;
+
+ if ( CombineMode > RGN_COPY && CombineMode < RGN_AND)
+ {
+ SetLastWin32Error(ERROR_INVALID_PARAMETER);
+ return ERROR;
+ }
+
+ destRgn = RGNOBJAPI_Lock(hDest, NULL);
+ if (!destRgn)
+ {
+ SetLastWin32Error(ERROR_INVALID_HANDLE);
+ return ERROR;
+ }
+
+ src1Rgn = RGNOBJAPI_Lock(hSrc1, NULL);
+ if (!src1Rgn)
+ {
+ RGNOBJAPI_Unlock(destRgn);
+ SetLastWin32Error(ERROR_INVALID_HANDLE);
+ return ERROR;
+ }
+
+ if (hSrc2)
+ src2Rgn = RGNOBJAPI_Lock(hSrc2, NULL);
+
+ result = IntGdiCombineRgn( destRgn, src1Rgn, src2Rgn, CombineMode);
+
+ if (src2Rgn)
+ RGNOBJAPI_Unlock(src2Rgn);
+ RGNOBJAPI_Unlock(src1Rgn);
+ RGNOBJAPI_Unlock(destRgn);
+
+ return result;
+}
+
+HRGN
+APIENTRY
+NtGdiCreateEllipticRgn(
+ INT Left,
+ INT Top,
+ INT Right,
+ INT Bottom
+)
+{
+ return NtGdiCreateRoundRectRgn(Left, Top, Right, Bottom,
+ Right - Left, Bottom - Top);
+}
+
+HRGN APIENTRY
+NtGdiCreateRectRgn(INT LeftRect, INT TopRect, INT RightRect, INT BottomRect)
+{
+ PROSRGNDATA pRgn;
+ HRGN hRgn;
+
+ /* Allocate region data structure with space for 1 RECTL */
+ if (!(pRgn = REGION_AllocRgnWithHandle(1)))
+ {
+ SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
+ return NULL;
+ }
+ hRgn = pRgn->BaseObject.hHmgr;
+
+ REGION_SetRectRgn(pRgn, LeftRect, TopRect, RightRect, BottomRect);
+ RGNOBJAPI_Unlock(pRgn);
+
+ return hRgn;
+}
+
+HRGN
+APIENTRY
+NtGdiCreateRoundRectRgn(
+ INT left,
+ INT top,
+ INT right,
+ INT bottom,
+ INT ellipse_width,
+ INT ellipse_height
+)
+{
+ PROSRGNDATA obj;
+ HRGN hrgn;
+ int asq, bsq, d, xd, yd;
+ RECTL rect;
+
+ /* Make the dimensions sensible */
+
+ if (left > right)
+ {
+ INT tmp = left;
+ left = right;
+ right = tmp;
+ }
+ if (top > bottom)
+ {
+ INT tmp = top;
+ top = bottom;
+ bottom = tmp;
+ }
+
+ ellipse_width = abs(ellipse_width);
+ ellipse_height = abs(ellipse_height);
+
+ /* Check parameters */
+
+ if (ellipse_width > right-left) ellipse_width = right-left;
+ if (ellipse_height > bottom-top) ellipse_height = bottom-top;
+
+ /* Check if we can do a normal rectangle instead */
+
+ if ((ellipse_width < 2) || (ellipse_height < 2))
+ return NtGdiCreateRectRgn(left, top, right, bottom);
+
+ /* Create region */
+
+ d = (ellipse_height < 128) ? ((3 * ellipse_height) >> 2) : 64;
+ if (!(obj = REGION_AllocRgnWithHandle(d))) return 0;
+ hrgn = obj->BaseObject.hHmgr;
+
+ /* Ellipse algorithm, based on an article by K. Porter */
+ /* in DDJ Graphics Programming Column, 8/89 */
+
+ asq = ellipse_width * ellipse_width / 4; /* a^2 */
+ bsq = ellipse_height * ellipse_height / 4; /* b^2 */
+ d = bsq - asq * ellipse_height / 2 + asq / 4; /* b^2 - a^2b + a^2/4 */
+ xd = 0;
+ yd = asq * ellipse_height; /* 2a^2b */
+
+ rect.left = left + ellipse_width / 2;
+ rect.right = right - ellipse_width / 2;
+
+ /* Loop to draw first half of quadrant */
+
+ while (xd < yd)
+ {
+ if (d > 0) /* if nearest pixel is toward the center */
+ {
+ /* move toward center */
+ rect.top = top++;
+ rect.bottom = rect.top + 1;
+ REGION_UnionRectWithRgn(obj, &rect);
+ rect.top = --bottom;
+ rect.bottom = rect.top + 1;
+ REGION_UnionRectWithRgn(obj, &rect);
+ yd -= 2*asq;
+ d -= yd;
+ }
+ rect.left--; /* next horiz point */
+ rect.right++;
+ xd += 2*bsq;
+ d += bsq + xd;
+ }
+ /* Loop to draw second half of quadrant */
+
+ d += (3 * (asq-bsq) / 2 - (xd+yd)) / 2;
+ while (yd >= 0)
+ {
+ /* next vertical point */
+ rect.top = top++;
+ rect.bottom = rect.top + 1;
+ REGION_UnionRectWithRgn(obj, &rect);
+ rect.top = --bottom;
+ rect.bottom = rect.top + 1;
+ REGION_UnionRectWithRgn(obj, &rect);
+ if (d < 0) /* if nearest pixel is outside ellipse */
+ {
+ rect.left--; /* move away from center */
+ rect.right++;
+ xd += 2*bsq;
+ d += xd;
+ }
+ yd -= 2*asq;
+ d += asq - yd;
+ }
+ /* Add the inside rectangle */
+
+ if (top <= bottom)
+ {
+ rect.top = top;
+ rect.bottom = bottom;
+ REGION_UnionRectWithRgn(obj, &rect);
+ }
+
+ RGNOBJAPI_Unlock(obj);
+ return hrgn;
+}
+
+BOOL
+APIENTRY
+NtGdiEqualRgn(
+ HRGN hSrcRgn1,
+ HRGN hSrcRgn2
+)
+{
+ PROSRGNDATA rgn1, rgn2;
+ PRECTL tRect1, tRect2;
+ ULONG i;
+ BOOL bRet = FALSE;
+
+ if ( !(rgn1 = RGNOBJAPI_Lock(hSrcRgn1, NULL)) )
+ return ERROR;
+
+ if ( !(rgn2 = RGNOBJAPI_Lock(hSrcRgn2, NULL)) )
+ {
+ RGNOBJAPI_Unlock(rgn1);
+ return ERROR;
+ }
+
+ if (rgn1->rdh.nCount != rgn2->rdh.nCount ||
+ rgn1->rdh.nCount == 0 ||
+ rgn1->rdh.rcBound.left != rgn2->rdh.rcBound.left ||
+ rgn1->rdh.rcBound.right != rgn2->rdh.rcBound.right ||
+ rgn1->rdh.rcBound.top != rgn2->rdh.rcBound.top ||
+ rgn1->rdh.rcBound.bottom != rgn2->rdh.rcBound.bottom)
+ goto exit;
+
+ tRect1 = rgn1->Buffer;
+ tRect2 = rgn2->Buffer;
+
+ if (!tRect1 || !tRect2)
+ goto exit;
+
+ for (i=0; i < rgn1->rdh.nCount; i++)
+ {
+ if (tRect1[i].left != tRect2[i].left ||
+ tRect1[i].right != tRect2[i].right ||
+ tRect1[i].top != tRect2[i].top ||
+ tRect1[i].bottom != tRect2[i].bottom)
+ goto exit;
+ }
+ bRet = TRUE;
+
+exit:
+ RGNOBJAPI_Unlock(rgn1);
+ RGNOBJAPI_Unlock(rgn2);
+ return bRet;
+}
+
+HRGN
+APIENTRY
+NtGdiExtCreateRegion(
+ OPTIONAL LPXFORM Xform,
+ DWORD Count,
+ LPRGNDATA RgnData
+)
+{
+ HRGN hRgn;
+ PROSRGNDATA Region;
+ DWORD nCount = 0;
+ DWORD iType = 0;
+ DWORD dwSize = 0;
+ NTSTATUS Status = STATUS_SUCCESS;
+ MATRIX matrix;
+
+ DPRINT("NtGdiExtCreateRegion\n");
+ _SEH2_TRY
+ {
+ ProbeForRead(RgnData, Count, 1);
+ nCount = RgnData->rdh.nCount;
+ iType = RgnData->rdh.iType;
+ dwSize = RgnData->rdh.dwSize;
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ Status = _SEH2_GetExceptionCode();
+ }
+ _SEH2_END;
+ if (!NT_SUCCESS(Status))
+ {
+ SetLastNtError(Status);
+ return NULL;
+ }
+
+ /* Check parameters, but don't set last error here */
+ if (Count < sizeof(RGNDATAHEADER) + nCount * sizeof(RECT) ||
+ iType != RDH_RECTANGLES ||
+ dwSize != sizeof(RGNDATAHEADER))
+ {
+ return NULL;
+ }
+
+ Region = REGION_AllocRgnWithHandle(nCount);
+
+ if (Region == NULL)
+ {
+ SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
+ return FALSE;
+ }
+ hRgn = Region->BaseObject.hHmgr;
+
+ _SEH2_TRY
+ {
+ if (Xform)
+ {
+ ULONG ret;
+
+ /* Init the XFORMOBJ from the Xform struct */
+ Status = STATUS_INVALID_PARAMETER;
+ ret = XFORMOBJ_iSetXform((XFORMOBJ*)&matrix, (XFORML*)Xform);
+
+ /* Check for error, also no scale and shear allowed */
+ if (ret != DDI_ERROR && ret != GX_GENERAL)
+ {
+ /* Apply the coordinate transformation on the rects */
+ if (XFORMOBJ_bApplyXform((XFORMOBJ*)&matrix,
+ XF_LTOL,
+ nCount * 2,
+ RgnData->Buffer,
+ Region->Buffer))
+ {
+ Status = STATUS_SUCCESS;
+ }
+ }
+ }
+ else
+ {
+ /* Copy rect coordinates */
+ RtlCopyMemory(Region->Buffer,
+ RgnData->Buffer,
+ nCount * sizeof(RECT));
+ }
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ Status = _SEH2_GetExceptionCode();
+ }
+ _SEH2_END;
+ if (!NT_SUCCESS(Status))
+ {
+ SetLastWin32Error(ERROR_INVALID_PARAMETER);
+ RGNOBJAPI_Unlock(Region);
+ GreDeleteObject(hRgn);
+ return NULL;
+ }
+
+ RGNOBJAPI_Unlock(Region);
+
+ return hRgn;
+}
+
+BOOL
+APIENTRY
+NtGdiFillRgn(
+ HDC hDC,
+ HRGN hRgn,
+ HBRUSH hBrush
+)
+{
+ HBRUSH oldhBrush;
+ PROSRGNDATA rgn;
+ PRECTL r;
+
+ if (NULL == (rgn = RGNOBJAPI_Lock(hRgn, NULL)))
+ {
+ return FALSE;
+ }
+
+ if (NULL == (oldhBrush = NtGdiSelectBrush(hDC, hBrush)))
+ {
+ RGNOBJAPI_Unlock(rgn);
+ return FALSE;
+ }
+
+ for (r = rgn->Buffer; r < rgn->Buffer + rgn->rdh.nCount; r++)
+ {
+ NtGdiPatBlt(hDC, r->left, r->top, r->right - r->left, r->bottom -
r->top, PATCOPY);
+ }
+
+ RGNOBJAPI_Unlock(rgn);
+ NtGdiSelectBrush(hDC, oldhBrush);
+
+ return TRUE;
+}
+
+BOOL
+APIENTRY
+NtGdiFrameRgn(
+ HDC hDC,
+ HRGN hRgn,
+ HBRUSH hBrush,
+ INT Width,
+ INT Height
+)
+{
+ HRGN FrameRgn;
+ BOOL Ret;
+
+ if (!(FrameRgn = NtGdiCreateRectRgn(0, 0, 0, 0)))
+ {
+ return FALSE;
+ }
+ if (!REGION_CreateFrameRgn(FrameRgn, hRgn, Width, Height))
+ {
+ GreDeleteObject(FrameRgn);
+ return FALSE;
+ }
+
+ Ret = NtGdiFillRgn(hDC, FrameRgn, hBrush);
+
+ GreDeleteObject(FrameRgn);
+ return Ret;
+}
+
+
+/* See wine, msdn, osr and Feng Yuan - Windows Graphics Programming Win32 Gdi And
Directdraw
+
+ 1st:
http://www.codeproject.com/gdi/cliprgnguide.asp is wrong!
+
+ The intersection of the clip with the meta region is not Rao it's API!
+ Go back and read 7.2 Clipping pages 418-19:
+ Rao = API & Vis:
+ 1) The Rao region is the intersection of the API region and the system region,
+ named after the Microsoft engineer who initially proposed it.
+ 2) The Rao region can be calculated from the API region and the system region.
+
+ API:
+ API region is the intersection of the meta region and the clipping region,
+ clearly named after the fact that it is controlled by GDI API calls.
+*/
+INT APIENTRY
+NtGdiGetRandomRgn(
+ HDC hDC,
+ HRGN hDest,
+ INT iCode
+)
+{
+ INT ret = 0;
+ PDC pDC;
+ HRGN hSrc = NULL;
+ POINT org;
+
+ pDC = DC_LockDc(hDC);
+ if (pDC == NULL)
+ {
+ SetLastWin32Error(ERROR_INVALID_HANDLE);
+ return -1;
+ }
+
+ switch (iCode)
+ {
+ case CLIPRGN:
+ hSrc = pDC->rosdc.hClipRgn;
+// if (pDC->dclevel.prgnClip) hSrc =
((PROSRGNDATA)pDC->dclevel.prgnClip)->BaseObject.hHmgr;
+ break;
+ case METARGN:
+ if (pDC->dclevel.prgnMeta) hSrc =
((PROSRGNDATA)pDC->dclevel.prgnMeta)->BaseObject.hHmgr;
+ break;
+ case APIRGN:
+ hSrc = pDC->rosdc.hClipRgn;
+// if (pDC->prgnAPI) hSrc =
((PROSRGNDATA)pDC->prgnAPI)->BaseObject.hHmgr;
+// else if (pDC->dclevel.prgnClip) hSrc =
((PROSRGNDATA)pDC->dclevel.prgnClip)->BaseObject.hHmgr;
+// else if (pDC->dclevel.prgnMeta) hSrc =
((PROSRGNDATA)pDC->dclevel.prgnMeta)->BaseObject.hHmgr;
+ break;
+ case SYSRGN:
+ hSrc = pDC->rosdc.hVisRgn;
+// if (pDC->prgnVis) hSrc =
((PROSRGNDATA)pDC->prgnVis)->BaseObject.hHmgr;
+ break;
+ default:
+ hSrc = 0;
+ }
+ if (hSrc)
+ {
+ if (NtGdiCombineRgn(hDest, hSrc, 0, RGN_COPY) == ERROR)
+ {
+ ret = -1;
+ }
+ else
+ {
+ ret = 1;
+ }
+ }
+ if (iCode == SYSRGN)
+ {
+ IntGdiGetDCOrg(pDC, &org);
+ NtGdiOffsetRgn(hDest, org.x, org.y );
+ }
+
+ DC_UnlockDc(pDC);
+
+ return ret;
+}
+
+INT APIENTRY
+NtGdiGetRgnBox(
+ HRGN hRgn,
+ PRECTL pRect
+)
+{
+ PROSRGNDATA Rgn;
+ RECTL SafeRect;
+ DWORD ret;
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ if (!(Rgn = RGNOBJAPI_Lock(hRgn, NULL)))
+ {
+ return ERROR;
+ }
+
+ ret = REGION_GetRgnBox(Rgn, &SafeRect);
+ RGNOBJAPI_Unlock(Rgn);
+ if (ERROR == ret)
+ {
+ return ret;
+ }
+
+ _SEH2_TRY
+ {
+ ProbeForWrite(pRect, sizeof(RECT), 1);
+ *pRect = SafeRect;
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ Status = _SEH2_GetExceptionCode();
+ }
+ _SEH2_END;
+ if (!NT_SUCCESS(Status))
+ {
+ return ERROR;
+ }
+
+ return ret;
+}
+
+BOOL
+APIENTRY
+NtGdiInvertRgn(
+ HDC hDC,
+ HRGN hRgn
+)
+{
+ PROSRGNDATA RgnData;
+ ULONG i;
+ PRECTL rc;
+
+ if (!(RgnData = RGNOBJAPI_Lock(hRgn, NULL)))
+ {
+ SetLastWin32Error(ERROR_INVALID_HANDLE);
+ return FALSE;
+ }
+
+ rc = RgnData->Buffer;
+ for (i = 0; i < RgnData->rdh.nCount; i++)
+ {
+
+ if (!NtGdiPatBlt(hDC, rc->left, rc->top, rc->right - rc->left,
rc->bottom - rc->top, DSTINVERT))
+ {
+ RGNOBJAPI_Unlock(RgnData);
+ return FALSE;
+ }
+ rc++;
+ }
+
+ RGNOBJAPI_Unlock(RgnData);
+ return TRUE;
+}
+
+INT
+APIENTRY
+NtGdiOffsetRgn(
+ HRGN hRgn,
+ INT XOffset,
+ INT YOffset
+)
+{
+ PROSRGNDATA rgn = RGNOBJAPI_Lock(hRgn, NULL);
+ INT ret;
+
+ DPRINT("NtGdiOffsetRgn: hRgn %d Xoffs %d Yoffs %d rgn %x\n", hRgn, XOffset,
YOffset, rgn );
+
+ if (!rgn)
+ {
+ DPRINT("NtGdiOffsetRgn: hRgn error\n");
+ return ERROR;
+ }
+
+ if (XOffset || YOffset)
+ {
+ int nbox = rgn->rdh.nCount;
+ PRECTL pbox = rgn->Buffer;
+
+ if (nbox && pbox)
+ {
+ while (nbox--)
+ {
+ pbox->left += XOffset;
+ pbox->right += XOffset;
+ pbox->top += YOffset;
+ pbox->bottom += YOffset;
+ pbox++;
+ }
+ if (rgn->Buffer != &rgn->rdh.rcBound)
+ {
+ rgn->rdh.rcBound.left += XOffset;
+ rgn->rdh.rcBound.right += XOffset;
+ rgn->rdh.rcBound.top += YOffset;
+ rgn->rdh.rcBound.bottom += YOffset;
+ }
+ }
+ }
+ ret = REGION_Complexity(rgn);
+ RGNOBJAPI_Unlock(rgn);
+ return ret;
+}
+
+BOOL
+APIENTRY
+NtGdiPtInRegion(
+ HRGN hRgn,
+ INT X,
+ INT Y
+)
+{
+ PROSRGNDATA rgn;
+ ULONG i;
+ PRECTL r;
+
+ if (!(rgn = RGNOBJAPI_Lock(hRgn, NULL) ) )
+ return FALSE;
+
+ if (rgn->rdh.nCount > 0 && INRECT(rgn->rdh.rcBound, X, Y))
+ {
+ r = rgn->Buffer;
+ for (i = 0; i < rgn->rdh.nCount; i++)
+ {
+ if (INRECT(*r, X, Y))
+ {
+ RGNOBJAPI_Unlock(rgn);
+ return TRUE;
+ }
+ r++;
+ }
+ }
+ RGNOBJAPI_Unlock(rgn);
+ return FALSE;
+}
+
+BOOL
+APIENTRY
+NtGdiRectInRegion(
+ HRGN hRgn,
+ LPRECTL unsaferc
+)
+{
+ PROSRGNDATA Rgn;
+ RECTL rc = {0};
+ BOOL Ret;
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ if (!(Rgn = RGNOBJAPI_Lock(hRgn, NULL)))
+ {
+ return ERROR;
+ }
+
+ _SEH2_TRY
+ {
+ ProbeForRead(unsaferc, sizeof(RECT), 1);
+ rc = *unsaferc;
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ Status = _SEH2_GetExceptionCode();
+ }
+ _SEH2_END;
+
+ if (!NT_SUCCESS(Status))
+ {
+ RGNOBJAPI_Unlock(Rgn);
+ SetLastNtError(Status);
+ DPRINT1("NtGdiRectInRegion: bogus rc\n");
+ return ERROR;
+ }
+
+ Ret = REGION_RectInRegion(Rgn, &rc);
+ RGNOBJAPI_Unlock(Rgn);
+ return Ret;
+}
+
+BOOL
+APIENTRY
+NtGdiSetRectRgn(
+ HRGN hRgn,
+ INT LeftRect,
+ INT TopRect,
+ INT RightRect,
+ INT BottomRect
+)
+{
+ PROSRGNDATA rgn;
+
+ if ( !(rgn = RGNOBJAPI_Lock(hRgn, NULL)) )
+ {
+ return 0; //per documentation
+ }
+
+ REGION_SetRectRgn(rgn, LeftRect, TopRect, RightRect, BottomRect);
+
+ RGNOBJAPI_Unlock(rgn);
+ return TRUE;
+}
+
+HRGN APIENTRY
+NtGdiUnionRectWithRgn(
+ HRGN hDest,
+ const RECTL *UnsafeRect
+)
+{
+ RECTL SafeRect = {0};
+ PROSRGNDATA Rgn;
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ if (!(Rgn = RGNOBJAPI_Lock(hDest, NULL)))
+ {
+ SetLastWin32Error(ERROR_INVALID_HANDLE);
+ return NULL;
+ }
+
+ _SEH2_TRY
+ {
+ ProbeForRead(UnsafeRect, sizeof(RECT), 1);
+ SafeRect = *UnsafeRect;
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ Status = _SEH2_GetExceptionCode();
+ }
+ _SEH2_END;
+
+ if (! NT_SUCCESS(Status))
+ {
+ RGNOBJAPI_Unlock(Rgn);
+ SetLastNtError(Status);
+ return NULL;
+ }
+
+ REGION_UnionRectWithRgn(Rgn, &SafeRect);
+ RGNOBJAPI_Unlock(Rgn);
+ return hDest;
+}
+
+/*!
+ * MSDN: GetRegionData, Return Values:
+ *
+ * "If the function succeeds and dwCount specifies an adequate number of bytes,
+ * the return value is always dwCount. If dwCount is too small or the function
+ * fails, the return value is 0. If lpRgnData is NULL, the return value is the
+ * required number of bytes.
+ *
+ * If the function fails, the return value is zero."
+ */
+DWORD APIENTRY
+NtGdiGetRegionData(
+ HRGN hrgn,
+ DWORD count,
+ LPRGNDATA rgndata
+)
+{
+ DWORD size;
+ PROSRGNDATA obj = RGNOBJAPI_Lock(hrgn, NULL);
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ if (!obj)
+ return 0;
+
+ size = obj->rdh.nCount * sizeof(RECT);
+ if (count < (size + sizeof(RGNDATAHEADER)) || rgndata == NULL)
+ {
+ RGNOBJAPI_Unlock(obj);
+ if (rgndata) /* buffer is too small, signal it by return 0 */
+ return 0;
+ else /* user requested buffer size with rgndata NULL */
+ return size + sizeof(RGNDATAHEADER);
+ }
+
+ _SEH2_TRY
+ {
+ ProbeForWrite(rgndata, count, 1);
+ RtlCopyMemory(rgndata, &obj->rdh, sizeof(RGNDATAHEADER));
+ RtlCopyMemory(rgndata->Buffer, obj->Buffer, size);
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ Status = _SEH2_GetExceptionCode();
+ }
+ _SEH2_END;
+
+ if (!NT_SUCCESS(Status))
+ {
+ SetLastNtError(Status);
+ RGNOBJAPI_Unlock(obj);
+ return 0;
+ }
+
+ RGNOBJAPI_Unlock(obj);
+ return size + sizeof(RGNDATAHEADER);
+}
+
/* EOF */