[ros-diffs] [jimtabor] 44923: - Another attempt to fix RGNOBJAPI_Un/Lock SEH issue. Resort code.

jimtabor at svn.reactos.org jimtabor at svn.reactos.org
Mon Jan 4 02:36:24 CET 2010


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/objects/region.c?rev=44923&r1=44922&r2=44923&view=diff
==============================================================================
--- 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 */




More information about the Ros-diffs mailing list