Beispiel #1
0
/*
 * @implemented
 *
 */
int
WINAPI
SetBkMode(
    _In_ HDC hdc,
    _In_ int iBkMode)
{
    PDC_ATTR pdcattr;
    INT iOldMode;

    HANDLE_METADC(INT, SetBkMode, 0, hdc, iBkMode);

    /* Get the DC attribute */
    pdcattr = GdiGetDcAttr(hdc);
    if (pdcattr == NULL)
    {
        SetLastError(ERROR_INVALID_PARAMETER);
        return 0;
    }

    iOldMode = pdcattr->lBkMode;
    pdcattr->jBkMode = iBkMode; // Processed
    pdcattr->lBkMode = iBkMode; // Raw

    return iOldMode;
}
Beispiel #2
0
/*
 * @implemented
 */
COLORREF
WINAPI
SetDCPenColor(
    _In_ HDC hdc,
    _In_ COLORREF crColor)
{
    PDC_ATTR pdcattr;
    COLORREF crOldColor;

    /* Get the DC attribute */
    pdcattr = GdiGetDcAttr(hdc);
    if (pdcattr == NULL)
    {
        SetLastError(ERROR_INVALID_PARAMETER);
        return CLR_INVALID;
    }

    /* We handle only enhanced meta DCs here */
    HANDLE_METADC(COLORREF, SetDCPenColor, CLR_INVALID, hdc, crColor);

    /* Get old color and store the new */
    crOldColor = pdcattr->ulPenClr;
    pdcattr->ulPenClr = (ULONG)crColor;

    if (pdcattr->crPenClr != crColor)
    {
        pdcattr->ulDirty_ |= DIRTY_LINE;
        pdcattr->crPenClr = crColor;
    }

    return crOldColor;
}
Beispiel #3
0
/*
 * @implemented
 */
COLORREF
WINAPI
SetBkColor(
    _In_ HDC hdc,
    _In_ COLORREF crColor)
{
    PDC_ATTR pdcattr;
    COLORREF crOldColor;

    HANDLE_METADC(COLORREF, SetBkColor, CLR_INVALID, hdc, crColor);

    /* Get the DC attribute */
    pdcattr = GdiGetDcAttr(hdc);
    if (pdcattr == NULL)
    {
        SetLastError(ERROR_INVALID_PARAMETER);
        return CLR_INVALID;
    }

    /* Get old color and store the new */
    crOldColor = pdcattr->ulBackgroundClr;
    pdcattr->ulBackgroundClr = crColor;

    if (pdcattr->crBackgroundClr != crColor)
    {
        pdcattr->ulDirty_ |= (DIRTY_BACKGROUND|DIRTY_LINE|DIRTY_FILL);
        pdcattr->crBackgroundClr = crColor;
    }

    return crOldColor;
}
Beispiel #4
0
HPEN
WINAPI
GdiSelectPen(
    _In_ HDC hdc,
    _In_ HPEN hpen)
{
    PDC_ATTR pdcattr;
    HPEN hpenOld;

    HANDLE_METADC(HPEN, SelectPen, NULL, hdc, hpen);

    /* Get the DC attribute */
    pdcattr = GdiGetDcAttr(hdc);
    if (pdcattr == NULL)
    {
        SetLastError(ERROR_INVALID_PARAMETER);
        return NULL;
    }

    /* Get the current pen. If it matches the new pen, we're done */
    hpenOld = pdcattr->hpen;
    if (hpenOld == hpen)
        return hpenOld;

    /* Set the new pen and update dirty flags */
    pdcattr->ulDirty_ |= DC_PEN_DIRTY;
    pdcattr->hpen = hpen;
    return hpenOld;
}
Beispiel #5
0
/*
 * @implemented
 */
int
WINAPI
SetStretchBltMode(
    _In_ HDC hdc,
    _In_ int iStretchMode)
{
    INT iOldMode;
    PDC_ATTR pdcattr;

    HANDLE_METADC(INT, SetStretchBltMode, 0, hdc, iStretchMode);

    /* Get the DC attribute */
    pdcattr = GdiGetDcAttr(hdc);
    if (pdcattr == NULL)
    {
        SetLastError(ERROR_INVALID_PARAMETER);
        return 0;
    }

    iOldMode = pdcattr->lStretchBltMode;
    pdcattr->lStretchBltMode = iStretchMode;

    // Wine returns an error here. We set the default.
    if ((iStretchMode <= 0) || (iStretchMode > MAXSTRETCHBLTMODE)) iStretchMode = WHITEONBLACK;

    pdcattr->jStretchBltMode = iStretchMode;

    return iOldMode;
}
Beispiel #6
0
HBRUSH
WINAPI
GdiSelectBrush(
    _In_ HDC hdc,
    _In_ HBRUSH hbr)
{
    PDC_ATTR pdcattr;
    HBRUSH hbrOld;

    HANDLE_METADC(HBRUSH, SelectBrush, NULL, hdc, hbr);

    /* Get the DC attribute */
    pdcattr = GdiGetDcAttr(hdc);
    if (pdcattr == NULL)
    {
        SetLastError(ERROR_INVALID_PARAMETER);
        return NULL;
    }

    /* Get the current brush. If it matches the new brush, we're done */
    hbrOld = pdcattr->hbrush;
    if (hbrOld == hbr)
        return hbrOld;

    /* Set the new brush and update dirty flags */
    pdcattr->hbrush = hbr;
    pdcattr->ulDirty_ |= DC_BRUSH_DIRTY;
    return hbrOld;
}
Beispiel #7
0
/*
 * @unimplemented
 */
int
WINAPI
SetPolyFillMode(
    _In_ HDC hdc,
    _In_ int iPolyFillMode)
{
    INT iOldPolyFillMode;
    PDC_ATTR pdcattr;

    HANDLE_METADC(INT, SetPolyFillMode, 0, hdc, iPolyFillMode);

    /* Get the DC attribute */
    pdcattr = GdiGetDcAttr(hdc);
    if (pdcattr == NULL)
    {
        SetLastError(ERROR_INVALID_PARAMETER);
        return 0;
    }

    if (NtCurrentTeb()->GdiTebBatch.HDC == hdc)
    {
        if (pdcattr->ulDirty_ & DC_MODE_DIRTY)
        {
            NtGdiFlush(); // Sync up pdcattr from Kernel space.
            pdcattr->ulDirty_ &= ~(DC_MODE_DIRTY|DC_FONTTEXT_DIRTY);
        }
    }

    iOldPolyFillMode = pdcattr->lFillMode;
    pdcattr->lFillMode = iPolyFillMode;

    return iOldPolyFillMode;
}
Beispiel #8
0
/*
 * @implemented
 */
int
WINAPI
SetROP2(
    _In_ HDC hdc,
    _In_ int rop2)
{
    PDC_ATTR pdcattr;
    INT rop2Old;

    HANDLE_METADC(INT, SetROP2, 0, hdc, rop2);

    /* Get the DC attribute */
    pdcattr = GdiGetDcAttr(hdc);
    if (pdcattr == NULL)
    {
        SetLastError(ERROR_INVALID_PARAMETER);
        return 0;
    }

    if (NtCurrentTeb()->GdiTebBatch.HDC == hdc)
    {
        if (pdcattr->ulDirty_ & DC_MODE_DIRTY)
        {
            NtGdiFlush();
            pdcattr->ulDirty_ &= ~DC_MODE_DIRTY;
        }
    }

    rop2Old = pdcattr->jROP2;
    pdcattr->jROP2 = (BYTE)rop2;

    return rop2Old;
}
Beispiel #9
0
/*
 * @unimplemented
 */
BOOL
WINAPI
RestoreDC(IN HDC hdc,
          IN INT iLevel)
{
    HANDLE_METADC(BOOL, RestoreDC, FALSE, hdc, iLevel);
    return NtGdiRestoreDC(hdc, iLevel);
}
Beispiel #10
0
/*
 * @implemented
 */
BOOL
WINAPI
SelectClipPath(
    HDC	hdc,
    int	iMode)
{
    HANDLE_METADC(BOOL, SelectClipPath, FALSE, hdc, iMode);
    return NtGdiSelectClipPath(hdc, iMode);
}
Beispiel #11
0
/*
 * @implemented
 */
INT
WINAPI
OffsetClipRgn(
    HDC hdc,
    INT nXOffset,
    INT nYOffset)
{
    HANDLE_METADC(INT, OffsetClipRgn, ERROR, hdc, nXOffset, nYOffset);
    return NtGdiOffsetClipRgn(hdc, nXOffset, nYOffset);
}
Beispiel #12
0
/*
 * @implemented
 */
BOOL
WINAPI
LineTo(
    _In_ HDC hdc,
    _In_ INT x,
    _In_ INT y )
{
    HANDLE_METADC(BOOL, LineTo, FALSE, hdc, x, y);

    return NtGdiLineTo(hdc, x, y);
}
Beispiel #13
0
HPALETTE
WINAPI
SelectPalette(
    HDC hdc,
    HPALETTE hpal,
    BOOL bForceBackground)
{
    HANDLE_METADC(HPALETTE, SelectPalette, NULL, hdc, hpal, bForceBackground);

    return NtUserSelectPalette(hdc, hpal, bForceBackground);
}
Beispiel #14
0
/*
 * @implemented
 */
COLORREF
WINAPI
SetPixel(
    _In_ HDC hdc,
    _In_ INT x,
    _In_ INT y,
    _In_ COLORREF crColor)
{
    HANDLE_METADC(COLORREF, SetPixel, CLR_INVALID, hdc, x, y, crColor);

    return NtGdiSetPixel(hdc, x, y, crColor);
}
Beispiel #15
0
/*
 * @implemented
 */
INT
WINAPI
IntersectClipRect(
    _In_ HDC hdc,
    _In_ INT nLeft,
    _In_ INT nTop,
    _In_ INT nRight,
    _In_ INT nBottom)
{
    HANDLE_METADC(INT, IntersectClipRect, ERROR, hdc, nLeft, nTop, nRight, nBottom);
    return NtGdiIntersectClipRect(hdc, nLeft, nTop, nRight, nBottom);
}
Beispiel #16
0
/*
 * @implemented
 */
INT
WINAPI
ExcludeClipRect(
    _In_ HDC hdc,
    _In_ INT xLeft,
    _In_ INT yTop,
    _In_ INT xRight,
    _In_ INT yBottom)
{
    HANDLE_METADC(INT, ExcludeClipRect, ERROR, hdc, xLeft, yTop, xRight, yBottom);

    return NtGdiExcludeClipRect(hdc, xLeft, yTop, xRight, yBottom);
}
Beispiel #17
0
/*
 * @implemented
 */
BOOL
WINAPI
Rectangle(
    _In_ HDC hdc,
    _In_ INT left,
    _In_ INT top,
    _In_ INT right,
    _In_ INT bottom)
{
    HANDLE_METADC(BOOL, Rectangle, FALSE, hdc, left, top, right, bottom);

    return NtGdiRectangle(hdc, left, top, right, bottom);
}
Beispiel #18
0
/*
 * @implemented
 */
BOOL
WINAPI
Ellipse(
    _In_ HDC hdc,
    _In_ INT left,
    _In_ INT top,
    _In_ INT right,
    _In_ INT bottom)
{
    HANDLE_METADC(BOOL, Ellipse, FALSE, hdc, left, top, right, bottom);

    return NtGdiEllipse(hdc, left, top, right, bottom);
}
Beispiel #19
0
/*
 * @implemented
 */
BOOL
WINAPI
InvertRgn(
    _In_ HDC hdc,
    _In_ HRGN hrgn)
{

    if (hrgn == NULL)
        return FALSE;

    HANDLE_METADC(BOOL, InvertRgn, FALSE, hdc, hrgn);

    return NtGdiInvertRgn(hdc, hrgn);
}
Beispiel #20
0
/*
 * @implemented
 */
BOOL
WINAPI
FillRgn(
    _In_ HDC hdc,
    _In_ HRGN hrgn,
    _In_ HBRUSH hbr)
{

    if ((hrgn == NULL) || (hbr == NULL))
        return FALSE;

    HANDLE_METADC(BOOL, FillRgn, FALSE, hdc, hrgn, hbr);

    return NtGdiFillRgn(hdc, hrgn, hbr);
}
Beispiel #21
0
/*
 * @implemented
 */
BOOL
WINAPI
RoundRect(
    _In_ HDC hdc,
    _In_ INT left,
    _In_ INT top,
    _In_ INT right,
    _In_ INT bottom,
    _In_ INT width,
    _In_ INT height)
{
    HANDLE_METADC(BOOL, RoundRect, FALSE, hdc, left, top, right, bottom, width, height);

    return NtGdiRoundRect(hdc, left, top, right, bottom, width, height);
}
Beispiel #22
0
/*
 * @implemented
 */
BOOL
WINAPI
FrameRgn(
    _In_ HDC hdc,
    _In_ HRGN hrgn,
    _In_ HBRUSH hbr,
    _In_ INT nWidth,
    _In_ INT nHeight)
{

    if ((hrgn == NULL) || (hbr == NULL))
        return FALSE;

    HANDLE_METADC(BOOL, FrameRgn, FALSE, hdc, hrgn, hbr, nWidth, nHeight);

    return NtGdiFrameRgn(hdc, hrgn, hbr, nWidth, nHeight);
}
Beispiel #23
0
HFONT
WINAPI
GdiSelectFont(
    _In_ HDC hdc,
    _In_ HFONT hfont)
{
    PDC_ATTR pdcattr;
    HFONT hfontOld;

    HANDLE_METADC(HFONT, SelectFont, NULL, hdc, hfont);

    /* Get the DC attribute */
    pdcattr = GdiGetDcAttr(hdc);
    if (pdcattr == NULL)
    {
        SetLastError(ERROR_INVALID_PARAMETER);
        return NULL;
    }

    /* Get the current font. If it matches the new font, we're done */
    hfontOld = pdcattr->hlfntNew;
    if (hfontOld == hfont)
        return hfontOld;

    /* Set the new font and update dirty flags */
    pdcattr->hlfntNew = hfont;
    pdcattr->ulDirty_ &= ~SLOW_WIDTHS;
    pdcattr->ulDirty_ |= DIRTY_CHARSET;

    /* If the DC does not have a DIB section selected, try a batch command */
    if (!(pdcattr->ulDirty_ & DC_DIBSECTION))
    {
        PGDIBSOBJECT pgO;

        pgO = GdiAllocBatchCommand(hdc, GdiBCSelObj);
        if (pgO)
        {
            pgO->hgdiobj = hfont;
            return hfontOld;
        }
    }

    /* We could not use the batch command, call win32k */
    return NtGdiSelectFont(hdc, hfont);
}
Beispiel #24
0
BOOL
WINAPI
MoveToEx(
    _In_ HDC hdc,
    _In_ INT x,
    _In_ INT y,
    _Out_opt_ LPPOINT ppt)
{
    PDC_ATTR pdcattr;

    HANDLE_METADC(BOOL, MoveTo, FALSE, hdc, x, y, ppt);

    /* Get the DC attribute */
    pdcattr = GdiGetDcAttr(hdc);
    if (pdcattr == NULL)
    {
        SetLastError(ERROR_INVALID_PARAMETER);
        return FALSE;
    }

    if (ppt)
    {
        if ( pdcattr->ulDirty_ & DIRTY_PTLCURRENT ) // Double hit!
        {
            ppt->x = pdcattr->ptfxCurrent.x; // ret prev before change.
            ppt->y = pdcattr->ptfxCurrent.y;
            DPtoLP (hdc, ppt, 1);          // reconvert back.
        }
        else
        {
            ppt->x = pdcattr->ptlCurrent.x;
            ppt->y = pdcattr->ptlCurrent.y;
        }
    }

    pdcattr->ptlCurrent.x = x;
    pdcattr->ptlCurrent.y = y;

    pdcattr->ulDirty_ &= ~DIRTY_PTLCURRENT;
    pdcattr->ulDirty_ |= ( DIRTY_PTFXCURRENT|DIRTY_STYLESTATE); // Set dirty
    return TRUE;
}
Beispiel #25
0
/*
 * @implemented
 *
 */
INT
WINAPI
SetDIBitsToDevice(
    HDC hdc,
    int XDest,
    int YDest,
    DWORD Width,
    DWORD Height,
    int XSrc,
    int YSrc,
    UINT StartScan,
    UINT ScanLines,
    CONST VOID *Bits,
    CONST BITMAPINFO *lpbmi,
    UINT ColorUse)
{
    PDC_ATTR pDc_Attr;
    PBITMAPINFO pConvertedInfo;
    UINT ConvertedInfoSize;
    INT LinesCopied = 0;
    UINT cjBmpScanSize = 0;
    BOOL Hit = FALSE;
    PVOID pvSafeBits = (PVOID) Bits;

    if (!ScanLines || !lpbmi || !Bits)
        return 0;

    if (ColorUse && ColorUse != DIB_PAL_COLORS && ColorUse != DIB_PAL_COLORS + 1)
        return 0;

    pConvertedInfo = ConvertBitmapInfo(lpbmi, ColorUse, &ConvertedInfoSize, FALSE);
    if (!pConvertedInfo)
        return 0;

    HANDLE_METADC(INT,
                  SetDIBitsToDevice,
                  0,
                  hdc,
                  XDest,
                  YDest,
                  Width,
                  Height,
                  XSrc,
                  YSrc,
                  StartScan,
                  ScanLines,
                  Bits,
                  lpbmi,
                  ColorUse);

    if ((pConvertedInfo->bmiHeader.biCompression == BI_RLE8) ||
            (pConvertedInfo->bmiHeader.biCompression == BI_RLE4))
    {
        /* For compressed data, we must set the whole thing */
        StartScan = 0;
        ScanLines = pConvertedInfo->bmiHeader.biHeight;
    }

    cjBmpScanSize = DIB_BitmapMaxBitsSize((LPBITMAPINFO) lpbmi, ScanLines);

    pvSafeBits = RtlAllocateHeap(GetProcessHeap(), 0, cjBmpScanSize);
    if (pvSafeBits)
    {
        _SEH2_TRY
        {
            RtlCopyMemory(pvSafeBits, Bits, cjBmpScanSize);
        }
        _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
        {
            Hit = TRUE;
        }
        _SEH2_END

        if (Hit)
        {
            // We don't die, we continue on with a allocated safe pointer to kernel
            // space.....
            DPRINT1("SetDIBitsToDevice fail to read BitMapInfo: %p or Bits: %p & Size: %u\n",
                pConvertedInfo, Bits, cjBmpScanSize);
        }
        DPRINT("SetDIBitsToDevice Allocate Bits %u!!!\n", cjBmpScanSize);
    }

    if (!GdiGetHandleUserData(hdc, GDI_OBJECT_TYPE_DC, (PVOID) & pDc_Attr))
    {
        SetLastError(ERROR_INVALID_PARAMETER);
        return 0;
    }
    /*
     if ( !pDc_Attr || // DC is Public
     ColorUse == DIB_PAL_COLORS ||
     ((pConvertedInfo->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER)) &&
     (pConvertedInfo->bmiHeader.biCompression == BI_JPEG ||
     pConvertedInfo->bmiHeader.biCompression  == BI_PNG )) )*/
    {
        LinesCopied = NtGdiSetDIBitsToDeviceInternal(hdc, XDest, YDest, Width, Height, XSrc, YSrc,
            StartScan, ScanLines, (LPBYTE) pvSafeBits, (LPBITMAPINFO) pConvertedInfo, ColorUse,
            cjBmpScanSize, ConvertedInfoSize,
            TRUE,
            NULL);
    }
    if (Bits != pvSafeBits)
        RtlFreeHeap(RtlGetProcessHeap(), 0, pvSafeBits);
    if (lpbmi != pConvertedInfo)
        RtlFreeHeap(RtlGetProcessHeap(), 0, pConvertedInfo);

    return LinesCopied;
}
Beispiel #26
0
/*
 * @implemented
 *
 */
int
WINAPI
GetDeviceCaps(
    _In_ HDC hdc,
    _In_ int nIndex)
{
    PDC_ATTR pdcattr;
    PDEVCAPS pDevCaps = GdiDevCaps; // Primary display device capabilities.
    DPRINT("Device CAPS1\n");

    HANDLE_METADC(INT, GetDeviceCaps, 0, hdc, nIndex);

    /* Get the DC attribute */
    pdcattr = GdiGetDcAttr(hdc);
    if (pdcattr == NULL)
    {
        SetLastError(ERROR_INVALID_PARAMETER);
        return 0;
    }

    if (!(pdcattr->ulDirty_ & DC_PRIMARY_DISPLAY))
        return NtGdiGetDeviceCaps(hdc, nIndex);

    switch (nIndex)
    {
    case DRIVERVERSION:
        return pDevCaps->ulVersion;

    case TECHNOLOGY:
        return pDevCaps->ulTechnology;

    case HORZSIZE:
        return pDevCaps->ulHorzSize;

    case VERTSIZE:
        return pDevCaps->ulVertSize;

    case HORZRES:
        return pDevCaps->ulHorzRes;

    case VERTRES:
        return pDevCaps->ulVertRes;

    case LOGPIXELSX:
        return pDevCaps->ulLogPixelsX;

    case LOGPIXELSY:
        return pDevCaps->ulLogPixelsY;

    case BITSPIXEL:
        return pDevCaps->ulBitsPixel;

    case PLANES:
        return pDevCaps->ulPlanes;

    case NUMBRUSHES:
        return -1;

    case NUMPENS:
        return pDevCaps->ulNumPens;

    case NUMFONTS:
        return pDevCaps->ulNumFonts;

    case NUMCOLORS:
        return pDevCaps->ulNumColors;

    case ASPECTX:
        return pDevCaps->ulAspectX;

    case ASPECTY:
        return pDevCaps->ulAspectY;

    case ASPECTXY:
        return pDevCaps->ulAspectXY;

    case CLIPCAPS:
        return CP_RECTANGLE;

    case SIZEPALETTE:
        return pDevCaps->ulSizePalette;

    case NUMRESERVED:
        return 20;

    case COLORRES:
        return pDevCaps->ulColorRes;

    case DESKTOPVERTRES:
        return pDevCaps->ulVertRes;

    case DESKTOPHORZRES:
        return pDevCaps->ulHorzRes;

    case BLTALIGNMENT:
        return pDevCaps->ulBltAlignment;

    case SHADEBLENDCAPS:
        return pDevCaps->ulShadeBlend;

    case COLORMGMTCAPS:
        return pDevCaps->ulColorMgmtCaps;

    case PHYSICALWIDTH:
        return pDevCaps->ulPhysicalWidth;

    case PHYSICALHEIGHT:
        return pDevCaps->ulPhysicalHeight;

    case PHYSICALOFFSETX:
        return pDevCaps->ulPhysicalOffsetX;

    case PHYSICALOFFSETY:
        return pDevCaps->ulPhysicalOffsetY;

    case VREFRESH:
        return pDevCaps->ulVRefresh;

    case RASTERCAPS:
        return pDevCaps->ulRasterCaps;

    case CURVECAPS:
        return (CC_CIRCLES | CC_PIE | CC_CHORD | CC_ELLIPSES | CC_WIDE |
                CC_STYLED | CC_WIDESTYLED | CC_INTERIORS | CC_ROUNDRECT);

    case LINECAPS:
        return (LC_POLYLINE | LC_MARKER | LC_POLYMARKER | LC_WIDE |
                LC_STYLED | LC_WIDESTYLED | LC_INTERIORS);

    case POLYGONALCAPS:
        return (PC_POLYGON | PC_RECTANGLE | PC_WINDPOLYGON | PC_SCANLINE |
                PC_WIDE | PC_STYLED | PC_WIDESTYLED | PC_INTERIORS);

    case TEXTCAPS:
        return pDevCaps->ulTextCaps;

    case PDEVICESIZE:
    case SCALINGFACTORX:
    case SCALINGFACTORY:
    default:
        return 0;
    }
    return 0;
}
Beispiel #27
0
/*
 * @implemented
 */
INT
WINAPI
ExtSelectClipRgn(
    _In_ HDC hdc,
    _In_ HRGN hrgn,
    _In_ INT iMode)
{
    INT Ret;
    HRGN NewRgn = NULL;

    HANDLE_METADC(INT, ExtSelectClipRgn, 0, hdc, hrgn, iMode);

#if 0
    if ( hrgn )
    {
        if ( GetLayout(hdc) & LAYOUT_RTL )
        {
            if ( MirrorRgnDC(hdc, hrgn, &NewRgn) )
            {
                if ( NewRgn ) hrgn = NewRgn;
            }
        }
    }
#endif
    /* Batch handles RGN_COPY only! */
    if (iMode == RGN_COPY)
    {
#if 0
        PDC_ATTR pDc_Attr;
        PRGN_ATTR pRgn_Attr = NULL;

        /* hrgn can be NULL unless the RGN_COPY mode is specified. */
        if (hrgn)
            GdiGetHandleUserData((HGDIOBJ) hrgn, GDI_OBJECT_TYPE_REGION, (PVOID) &pRgn_Attr);

        if ( GdiGetHandleUserData((HGDIOBJ) hdc, GDI_OBJECT_TYPE_DC, (PVOID) &pDc_Attr) &&
                pDc_Attr )
        {
            PGDI_TABLE_ENTRY pEntry = GdiHandleTable + GDI_HANDLE_GET_INDEX(hdc);
            PTEB pTeb = NtCurrentTeb();

            if ( pTeb->Win32ThreadInfo != NULL &&
                    pTeb->GdiTebBatch.HDC == hdc &&
                    !(pDc_Attr->ulDirty_ & DC_DIBSECTION) &&
                    !(pEntry->Flags & GDI_ENTRY_VALIDATE_VIS) )
            {
                if (!hrgn ||
                        (hrgn && pRgn_Attr && pRgn_Attr->iComplexity <= SIMPLEREGION) )
                {
                    if ((pTeb->GdiTebBatch.Offset + sizeof(GDIBSEXTSELCLPRGN)) <= GDIBATCHBUFSIZE)
                    {
                        // FIXME: This is broken, use GdiAllocBatchCommand!
                        PGDIBSEXTSELCLPRGN pgO = (PGDIBSEXTSELCLPRGN)(&pTeb->GdiTebBatch.Buffer[0] +
                                                 pTeb->GdiTebBatch.Offset);
                        pgO->gbHdr.Cmd = GdiBCExtSelClipRgn;
                        pgO->gbHdr.Size = sizeof(GDIBSEXTSELCLPRGN);
                        pgO->fnMode = iMode;

                        if ( hrgn && pRgn_Attr )
                        {
                            Ret = pRgn_Attr->iComplexity;

                            if ( pDc_Attr->VisRectRegion.Rect.left   >= pRgn_Attr->Rect.right  ||
                                    pDc_Attr->VisRectRegion.Rect.top    >= pRgn_Attr->Rect.bottom ||
                                    pDc_Attr->VisRectRegion.Rect.right  <= pRgn_Attr->Rect.left   ||
                                    pDc_Attr->VisRectRegion.Rect.bottom <= pRgn_Attr->Rect.top )
                                Ret = NULLREGION;

                            pgO->left   = pRgn_Attr->Rect.left;
                            pgO->top    = pRgn_Attr->Rect.top;
                            pgO->right  = pRgn_Attr->Rect.right;
                            pgO->bottom = pRgn_Attr->Rect.bottom;
                        }
                        else
                        {
                            Ret = pDc_Attr->VisRectRegion.Flags;
                            pgO->fnMode |= 0x80000000; // Set no hrgn mode.
                        }
                        pTeb->GdiTebBatch.Offset += sizeof(GDIBSEXTSELCLPRGN);
                        pTeb->GdiBatchCount++;
                        if (pTeb->GdiBatchCount >= GDI_BatchLimit) NtGdiFlush();
                        if ( NewRgn ) DeleteObject(NewRgn);
                        return Ret;
                    }
                }
            }
        }
#endif
    }
    Ret = NtGdiExtSelectClipRgn(hdc, hrgn, iMode);

    if ( NewRgn ) DeleteObject(NewRgn);

    return Ret;
}