Sync with trunk (r48545)
authorJérôme Gardou <jerome.gardou@reactos.org>
Sat, 14 Aug 2010 15:15:44 +0000 (15:15 +0000)
committerJérôme Gardou <jerome.gardou@reactos.org>
Sat, 14 Aug 2010 15:15:44 +0000 (15:15 +0000)
svn path=/branches/reactos-yarotows/; revision=48547

176 files changed:
1  2 
base/applications/taskmgr/applpage.c
base/applications/taskmgr/debug.c
base/applications/taskmgr/endproc.c
base/applications/taskmgr/graph.c
base/applications/taskmgr/graphctl.c
base/applications/taskmgr/graphctl.h
base/applications/taskmgr/optnmenu.c
base/applications/taskmgr/perfdata.c
base/applications/taskmgr/perfpage.c
base/applications/taskmgr/procpage.c
base/applications/taskmgr/taskmgr.c
base/applications/taskmgr/taskmgr.h
base/system/winlogon/winlogon.c
dll/win32/dhcpcsvc/dhcp/adapter.c
dll/win32/iphlpapi/iphlpapi_main.c
dll/win32/iphlpapi/iphlpapi_private.h
dll/win32/kernel32/file/backup.c
dll/win32/kernel32/file/bintype.c
dll/win32/kernel32/file/cnotify.c
dll/win32/kernel32/file/copy.c
dll/win32/kernel32/file/create.c
dll/win32/kernel32/file/curdir.c
dll/win32/kernel32/file/delete.c
dll/win32/kernel32/file/deviceio.c
dll/win32/kernel32/file/dir.c
dll/win32/kernel32/file/dosdev.c
dll/win32/kernel32/file/file.c
dll/win32/kernel32/file/find.c
dll/win32/kernel32/file/hardlink.c
dll/win32/kernel32/file/iocompl.c
dll/win32/kernel32/file/lfile.c
dll/win32/kernel32/file/lock.c
dll/win32/kernel32/file/mailslot.c
dll/win32/kernel32/file/move.c
dll/win32/kernel32/file/npipe.c
dll/win32/kernel32/file/pipe.c
dll/win32/kernel32/file/rw.c
dll/win32/kernel32/file/tape.c
dll/win32/kernel32/file/volume.c
dll/win32/kernel32/include/kernel32.h
dll/win32/kernel32/kernel32.def
dll/win32/kernel32/kernel32.pspec
dll/win32/kernel32/kernel32.rbuild
dll/win32/kernel32/misc/actctx.c
dll/win32/kernel32/misc/console.c
dll/win32/kernel32/misc/format_msg.c
dll/win32/kernel32/misc/lcformat.c
dll/win32/kernel32/misc/profile.c
dll/win32/kernel32/misc/stubs.c
dll/win32/kernel32/misc/version.c
dll/win32/kernel32/process/session.c
dll/win32/msafd/misc/dllmain.c
dll/win32/msvcrt/msvcrt.spec
dll/win32/shell32/iconcache.c
dll/win32/shlwapi/string.c
dll/win32/ws2_32/misc/dllmain.c
drivers/bus/pcix/device.c
drivers/bus/pcix/enum.c
drivers/bus/pcix/pci.h
drivers/bus/pcix/utils.c
drivers/filesystems/cdfs/fsctl.c
drivers/filesystems/cdfs/misc.c
drivers/filesystems/fastfat/create.c
drivers/filesystems/fastfat_new/cleanup.c
drivers/filesystems/fastfat_new/close.c
drivers/filesystems/fastfat_new/create.c
drivers/filesystems/fastfat_new/dir.c
drivers/filesystems/fastfat_new/fastfat.c
drivers/filesystems/fastfat_new/fastfat.h
drivers/filesystems/fastfat_new/fat.c
drivers/filesystems/fastfat_new/fatstruc.h
drivers/filesystems/fastfat_new/fcb.c
drivers/filesystems/fastfat_new/finfo.c
drivers/filesystems/fastfat_new/fsctl.c
drivers/filesystems/fastfat_new/lock.c
drivers/filesystems/fastfat_new/rw.c
drivers/filesystems/fastfat_new/volume.c
drivers/network/ndis/include/miniport.h
include/ddk/acpiioct.h
include/ddk/bdasup.h
include/ddk/d3dhal.h
include/ddk/d3dhalex.h
include/ddk/dmusicks.h
include/ddk/drivinit.h
include/ddk/drmk.h
include/ddk/dxapi.h
include/ddk/hubbusif.h
include/ddk/ide.h
include/ddk/ioaccess.h
include/ddk/mcd.h
include/ddk/mce.h
include/ddk/miniport.h
include/ddk/minitape.h
include/ddk/mountmgr.h
include/ddk/ndis.h
include/ddk/ndistapi.h
include/ddk/ndiswan.h
include/ddk/ntddpcm.h
include/ddk/ntddsnd.h
include/ddk/ntimage.h
include/ddk/ntnls.h
include/ddk/ntpoapi.h
include/ddk/ntstrsafe.h
include/ddk/oprghdlr.h
include/ddk/portcls.h
include/ddk/punknown.h
include/ddk/smbus.h
include/ddk/stdunk.h
include/ddk/storport.h
include/ddk/strmini.h
include/ddk/swenum.h
include/ddk/tdikrnl.h
include/ddk/tdistat.h
include/ddk/upssvc.h
include/ddk/usbbusif.h
include/ddk/usbdlib.h
include/ddk/usbprotocoldefs.h
include/ddk/wdm.h
include/ddk/wmilib.h
include/psdk/d3dnthal.h
include/psdk/ddkernel.h
include/psdk/ddkmapi.h
include/psdk/ddraw.h
include/psdk/ddrawi.h
include/psdk/ddrawint.h
include/psdk/dinput.h
include/psdk/diskguid.h
include/psdk/dmemmgr.h
include/psdk/dmksctrl.h
include/psdk/driverspecs.h
include/psdk/dvp.h
include/psdk/hidpi.h
include/psdk/hidusage.h
include/psdk/ieverp.h
include/psdk/imm.h
include/psdk/ntdd1394.h
include/psdk/ntdd8042.h
include/psdk/ntddbeep.h
include/psdk/ntddcdrm.h
include/psdk/ntddcdvd.h
include/psdk/ntdddisk.h
include/psdk/ntddft.h
include/psdk/ntddndis.h
include/psdk/ntddpar.h
include/psdk/ntddser.h
include/psdk/ntddtape.h
include/psdk/ntddtdi.h
include/psdk/ntddvdeo.h
include/psdk/ntddvol.h
include/psdk/objerror.h
include/psdk/polarity.h
include/psdk/prntfont.h
include/psdk/sti.h
include/psdk/stierr.h
include/psdk/stireg.h
include/psdk/tdi.h
include/psdk/tdiinfo.h
include/psdk/unknown.h
include/psdk/warning.h
include/psdk/winddi.h
include/reactos/debug.h
include/reactos/wine/ddk/imm.h
include/reactos/wine/imm.h
include/xdk/exfuncs.h
include/xdk/iofuncs.h
include/xdk/iotypes.h
include/xdk/ketypes.h
include/xdk/wmifuncs.h
include/xdk/x86/ke.h
lib/sdk/crt/locale/locale.c
ntoskrnl/ex/init.c
subsystems/win32/win32k/eng/bitblt.c
subsystems/win32/win32k/include/xlateobj.h
subsystems/win32/win32k/ntuser/cursoricon.c
subsystems/win32/win32k/objects/bitblt.c
subsystems/win32/win32k/objects/bitmaps.c

Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
index 0000000,f0130a9..f0130a9
mode 000000,100644..100644
--- /dev/null
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
index 0000000,ff712a7..ff712a7
mode 000000,100644..100644
--- /dev/null
index 0000000,8ffedf8..8ffedf8
mode 000000,100644..100644
--- /dev/null
Simple merge
Simple merge
index 0000000,2f676e9..2f676e9
mode 000000,100644..100644
--- /dev/null
index 0000000,927e7f8..927e7f8
mode 000000,100644..100644
--- /dev/null
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
index 0000000,ab3b41e..ab3b41e
mode 000000,100644..100644
--- /dev/null
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
index 0000000,29242f3..29242f3
mode 000000,100644..100644
--- /dev/null
index 0000000,a41831d..a41831d
mode 000000,100644..100644
--- /dev/null
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
index 92e9095,0000000..9077df7
mode 100644,000000..100644
--- /dev/null
@@@ -1,973 -1,0 +1,973 @@@
-     if (R4_MASK == rop4)
 +/*
 + * COPYRIGHT:        See COPYING in the top level directory
 + * PROJECT:          ReactOS kernel
 + * PURPOSE:          GDI BitBlt Functions
 + * FILE:             subsys/win32k/eng/bitblt.c
 + * PROGRAMER:        Jason Filby
 + *                   Timo Kreuzer
 + * REVISION HISTORY:
 + *        2/10/1999: Created
 + */
 +
 +#include <win32k.h>
 +
 +#define NDEBUG
 +#include <debug.h>
 +
 +typedef BOOLEAN (APIENTRY *PBLTRECTFUNC)(SURFOBJ* OutputObj,
 +                                        SURFOBJ* InputObj,
 +                                        SURFOBJ* Mask,
 +                                        XLATEOBJ* ColorTranslation,
 +                                        RECTL* OutputRect,
 +                                        POINTL* InputPoint,
 +                                        POINTL* MaskOrigin,
 +                                        BRUSHOBJ* pbo,
 +                                        POINTL* BrushOrigin,
 +                                        ROP4 Rop4);
 +
 +static BOOLEAN APIENTRY
 +BltMask(SURFOBJ* psoDest,
 +        SURFOBJ* psoSource, // unused
 +        SURFOBJ* psoMask,
 +        XLATEOBJ* ColorTranslation,  // unused
 +        RECTL* prclDest,
 +        POINTL* pptlSource, // unused
 +        POINTL* pptlMask,
 +        BRUSHOBJ* pbo,
 +        POINTL* pptlBrush,
 +        ROP4 Rop4)
 +{
 +    LONG x, y;
 +    BYTE *pjMskLine, *pjMskCurrent;
 +    BYTE fjMaskBit0, fjMaskBit;
 +    /* Pattern brushes */
 +    PEBRUSHOBJ pebo = NULL;
 +    SURFOBJ *psoPattern = NULL;
 +    PSURFACE psurfPattern;
 +    ULONG PatternWidth = 0, PatternHeight = 0;
 +    LONG PatternX0 = 0, PatternX = 0, PatternY = 0;
 +    PFN_DIB_PutPixel fnDest_PutPixel = NULL;
 +    PFN_DIB_GetPixel fnPattern_GetPixel = NULL;
 +    ULONG Pattern = 0;
 +    HBITMAP hbmPattern;
 +
 +    ASSERT(psoSource == NULL);
 +    ASSERT(pptlSource == NULL);
 +
 +    if (psoMask == NULL)
 +    {
 +        return FALSE;
 +    }
 +
 +    if (pbo && pbo->iSolidColor == 0xFFFFFFFF)
 +    {
 +        pebo = CONTAINING_RECORD(pbo, EBRUSHOBJ, BrushObject);
 +
 +        hbmPattern = EBRUSHOBJ_pvGetEngBrush(pebo);
 +        psurfPattern = SURFACE_LockSurface(hbmPattern);
 +        if (psurfPattern != NULL)
 +        {
 +            psoPattern = &psurfPattern->SurfObj;
 +            PatternWidth = psoPattern->sizlBitmap.cx;
 +            PatternHeight = psoPattern->sizlBitmap.cy;
 +            fnPattern_GetPixel = DibFunctionsForBitmapFormat[psoPattern->iBitmapFormat].DIB_GetPixel;
 +        }
 +    }
 +    else
 +        psurfPattern = NULL;
 +
 +    pjMskLine = (PBYTE)psoMask->pvScan0 + pptlMask->y * psoMask->lDelta + (pptlMask->x >> 3);
 +    fjMaskBit0 = 0x80 >> (pptlMask->x & 0x07);
 +
 +    fnDest_PutPixel = DibFunctionsForBitmapFormat[psoDest->iBitmapFormat].DIB_PutPixel;
 +    if (psurfPattern)
 +    {
 +        PatternY = (prclDest->top - pptlBrush->y) % PatternHeight;
 +        if (PatternY < 0)
 +        {
 +            PatternY += PatternHeight;
 +        }
 +        PatternX0 = (prclDest->left - pptlBrush->x) % PatternWidth;
 +        if (PatternX0 < 0)
 +        {
 +            PatternX0 += PatternWidth;
 +        }
 +
 +        for (y = prclDest->top; y < prclDest->bottom; y++)
 +        {
 +            pjMskCurrent = pjMskLine;
 +            fjMaskBit = fjMaskBit0;
 +            PatternX = PatternX0;
 +
 +            for (x = prclDest->left; x < prclDest->right; x++)
 +            {
 +                if (*pjMskCurrent & fjMaskBit)
 +                {
 +                    fnDest_PutPixel(psoDest, x, y,
 +                        fnPattern_GetPixel(psoPattern, PatternX, PatternY));
 +                }
 +                fjMaskBit = _rotr8(fjMaskBit, 1);
 +                pjMskCurrent += (fjMaskBit >> 7);
 +                PatternX++;
 +                PatternX %= PatternWidth;
 +            }
 +            pjMskLine += psoMask->lDelta;
 +            PatternY++;
 +            PatternY %= PatternHeight;
 +        }
 +    }
 +    else
 +    {
 +        Pattern = pbo ? pbo->iSolidColor : 0;
 +        for (y = prclDest->top; y < prclDest->bottom; y++)
 +        {
 +            pjMskCurrent = pjMskLine;
 +            fjMaskBit = fjMaskBit0;
 +
 +            for (x = prclDest->left; x < prclDest->right; x++)
 +            {
 +                if (*pjMskCurrent & fjMaskBit)
 +                {
 +                     fnDest_PutPixel(psoDest, x, y, Pattern);
 +                }
 +                fjMaskBit = _rotr8(fjMaskBit, 1);
 +                pjMskCurrent += (fjMaskBit >> 7);
 +            }
 +            pjMskLine += psoMask->lDelta;
 +        }
 +    }
 +
 +    if (psurfPattern)
 +        SURFACE_UnlockSurface(psurfPattern);
 +
 +    return TRUE;
 +}
 +
 +static BOOLEAN APIENTRY
 +BltPatCopy(SURFOBJ* Dest,
 +           SURFOBJ* Source,
 +           SURFOBJ* Mask,
 +           XLATEOBJ* ColorTranslation,
 +           RECTL* DestRect,
 +           POINTL* SourcePoint,
 +           POINTL* MaskPoint,
 +           BRUSHOBJ* pbo,
 +           POINTL* BrushPoint,
 +           ROP4 Rop4)
 +{
 +    // These functions are assigned if we're working with a DIB
 +    // The assigned functions depend on the bitsPerPixel of the DIB
 +
 +    DibFunctionsForBitmapFormat[Dest->iBitmapFormat].DIB_ColorFill(Dest, DestRect, pbo ? pbo->iSolidColor : 0);
 +
 +    return TRUE;
 +}
 +
 +static BOOLEAN APIENTRY
 +CallDibBitBlt(SURFOBJ* OutputObj,
 +              SURFOBJ* InputObj,
 +              SURFOBJ* Mask,
 +              XLATEOBJ* ColorTranslation,
 +              RECTL* OutputRect,
 +              POINTL* InputPoint,
 +              POINTL* MaskOrigin,
 +              BRUSHOBJ* pbo,
 +              POINTL* BrushOrigin,
 +              ROP4 Rop4)
 +{
 +    BLTINFO BltInfo;
 +    PEBRUSHOBJ GdiBrush = NULL;
 +    SURFACE *psurfPattern;
 +    BOOLEAN Result;
 +    HBITMAP hbmPattern;
 +
 +    BltInfo.DestSurface = OutputObj;
 +    BltInfo.SourceSurface = InputObj;
 +    BltInfo.PatternSurface = NULL;
 +    BltInfo.XlateSourceToDest = ColorTranslation;
 +    BltInfo.DestRect = *OutputRect;
 +    BltInfo.SourcePoint = *InputPoint;
 +
 +    if (ROP3_TO_ROP4(SRCCOPY) == Rop4)
 +        return DibFunctionsForBitmapFormat[OutputObj->iBitmapFormat].DIB_BitBltSrcCopy(&BltInfo);
 +
 +    BltInfo.Brush = pbo;
 +    BltInfo.BrushOrigin = *BrushOrigin;
 +    BltInfo.Rop4 = Rop4;
 +
 +    /* Pattern brush */
 +    if (ROP4_USES_PATTERN(Rop4) && pbo && pbo->iSolidColor == 0xFFFFFFFF)
 +    {
 +        GdiBrush = CONTAINING_RECORD(pbo, EBRUSHOBJ, BrushObject);
 +        hbmPattern = EBRUSHOBJ_pvGetEngBrush(GdiBrush);
 +        psurfPattern = SURFACE_LockSurface(hbmPattern);
 +        if (psurfPattern)
 +        {
 +            BltInfo.PatternSurface = &psurfPattern->SurfObj;
 +        }
 +        else
 +        {
 +            /* FIXME - What to do here? */
 +        }
 +    }
 +    else
 +    {
 +        psurfPattern = NULL;
 +    }
 +
 +    Result = DibFunctionsForBitmapFormat[OutputObj->iBitmapFormat].DIB_BitBlt(&BltInfo);
 +
 +    /* Pattern brush */
 +    if (psurfPattern)
 +    {
 +        SURFACE_UnlockSurface(psurfPattern);
 +    }
 +
 +    return Result;
 +}
 +
 +INT __cdecl abs(INT nm);
 +
 +
 +/*
 + * @implemented
 + */
 +BOOL APIENTRY
 +NtGdiEngBitBlt(
 +                IN SURFOBJ  *psoTrg,
 +                IN SURFOBJ  *psoSrc,
 +                IN SURFOBJ  *psoMask,
 +                IN CLIPOBJ  *pco,
 +                IN XLATEOBJ  *pxlo,
 +                IN RECTL  *prclTrg,
 +                IN POINTL  *pptlSrc,
 +                IN POINTL  *pptlMask,
 +                IN BRUSHOBJ  *pbo,
 +                IN POINTL  *pptlBrush,
 +                IN ROP4  rop4    )
 +{
 +    RECTL  rclTrg;
 +    POINTL ptlSrc;
 +    POINTL ptlMask;
 +    POINTL ptlBrush;
 +
 +    _SEH2_TRY
 +    {
 +        ProbeForRead(prclTrg, sizeof(RECTL), 1);
 +        RtlCopyMemory(&rclTrg,prclTrg, sizeof(RECTL));
 +
 +        ProbeForRead(pptlSrc, sizeof(POINTL), 1);
 +        RtlCopyMemory(&ptlSrc, pptlSrc, sizeof(POINTL));
 +
 +        ProbeForRead(pptlMask, sizeof(POINTL), 1);
 +        RtlCopyMemory(&ptlMask, pptlMask, sizeof(POINTL));
 +
 +        ProbeForRead(pptlBrush, sizeof(POINTL), 1);
 +        RtlCopyMemory(&ptlBrush, pptlBrush, sizeof(POINTL));
 +
 +    }
 +    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
 +    {
 +        _SEH2_YIELD(return FALSE);
 +    }
 +    _SEH2_END;
 +
 +    return  EngBitBlt(psoTrg, psoSrc, psoMask, pco, pxlo, &rclTrg, &ptlSrc, &ptlMask, pbo, &ptlBrush, rop4);
 +}
 +
 +/*
 + * @implemented
 + */
 +BOOL APIENTRY
 +EngBitBlt(SURFOBJ *DestObj,
 +          SURFOBJ *SourceObj,
 +          SURFOBJ *Mask,
 +          CLIPOBJ *ClipRegion,
 +          XLATEOBJ *ColorTranslation,
 +          RECTL *DestRect,
 +          POINTL *SourcePoint,
 +          POINTL *MaskOrigin,
 +          BRUSHOBJ *pbo,
 +          POINTL *BrushOrigin,
 +          ROP4 rop4)
 +{
 +    BYTE               clippingType;
 +    RECTL              CombinedRect;
 +    RECT_ENUM          RectEnum;
 +    BOOL               EnumMore;
 +    POINTL             InputPoint;
 +    RECTL              InputRect;
 +    RECTL              OutputRect;
 +    SURFOBJ*           InputObj = 0;
 +    SURFOBJ*           OutputObj;
 +    PBLTRECTFUNC       BltRectFunc;
 +    BOOLEAN            Ret = TRUE;
 +    RECTL              ClipRect;
 +    unsigned           i;
 +    POINTL             Pt;
 +    ULONG              Direction;
 +    BOOL               UsesSource;
 +    BOOL               UsesPattern;
 +    POINTL             AdjustedBrushOrigin;
 +
 +    UsesSource = ROP4_USES_SOURCE(rop4);
 +    UsesPattern = ROP4_USES_PATTERN(rop4);
 +    if (R4_NOOP == rop4)
 +    {
 +        /* Copy destination onto itself: nop */
 +        return TRUE;
 +    }
 +
 +    OutputRect = *DestRect;
 +    if (OutputRect.right < OutputRect.left)
 +    {
 +        OutputRect.left = DestRect->right;
 +        OutputRect.right = DestRect->left;
 +    }
 +    if (OutputRect.bottom < OutputRect.top)
 +    {
 +        OutputRect.left = DestRect->right;
 +        OutputRect.right = DestRect->left;
 +    }
 +
 +    if (UsesSource)
 +    {
 +        if (NULL == SourcePoint)
 +        {
 +            return FALSE;
 +        }
 +
 +        /* Make sure we don't try to copy anything outside the valid source
 +           region */
 +        InputPoint = *SourcePoint;
 +        if (InputPoint.x < 0)
 +        {
 +            OutputRect.left -= InputPoint.x;
 +            InputPoint.x = 0;
 +        }
 +        if (InputPoint.y < 0)
 +        {
 +            OutputRect.top -= InputPoint.y;
 +            InputPoint.y = 0;
 +        }
 +        if (SourceObj->sizlBitmap.cx < InputPoint.x +
 +                OutputRect.right - OutputRect.left)
 +        {
 +            OutputRect.right = OutputRect.left +
 +                               SourceObj->sizlBitmap.cx - InputPoint.x;
 +        }
 +        if (SourceObj->sizlBitmap.cy < InputPoint.y +
 +                OutputRect.bottom - OutputRect.top)
 +        {
 +            OutputRect.bottom = OutputRect.top +
 +                                SourceObj->sizlBitmap.cy - InputPoint.y;
 +        }
 +
 +        InputRect.left = InputPoint.x;
 +        InputRect.right = InputPoint.x + (OutputRect.right - OutputRect.left);
 +        InputRect.top = InputPoint.y;
 +        InputRect.bottom = InputPoint.y + (OutputRect.bottom - OutputRect.top);
 +
 +        InputObj = SourceObj;
 +    }
 +    else
 +    {
 +        InputRect.left = 0;
 +        InputRect.right = DestRect->right - DestRect->left;
 +        InputRect.top = 0;
 +        InputRect.bottom = DestRect->bottom - DestRect->top;
 +    }
 +
 +    if (NULL != ClipRegion)
 +    {
 +        if (OutputRect.left < ClipRegion->rclBounds.left)
 +        {
 +            InputRect.left += ClipRegion->rclBounds.left - OutputRect.left;
 +            InputPoint.x += ClipRegion->rclBounds.left - OutputRect.left;
 +            OutputRect.left = ClipRegion->rclBounds.left;
 +        }
 +        if (ClipRegion->rclBounds.right < OutputRect.right)
 +        {
 +            InputRect.right -=  OutputRect.right - ClipRegion->rclBounds.right;
 +            OutputRect.right = ClipRegion->rclBounds.right;
 +        }
 +        if (OutputRect.top < ClipRegion->rclBounds.top)
 +        {
 +            InputRect.top += ClipRegion->rclBounds.top - OutputRect.top;
 +            InputPoint.y += ClipRegion->rclBounds.top - OutputRect.top;
 +            OutputRect.top = ClipRegion->rclBounds.top;
 +        }
 +        if (ClipRegion->rclBounds.bottom < OutputRect.bottom)
 +        {
 +            InputRect.bottom -=  OutputRect.bottom - ClipRegion->rclBounds.bottom;
 +            OutputRect.bottom = ClipRegion->rclBounds.bottom;
 +        }
 +    }
 +
 +    /* Check for degenerate case: if height or width of OutputRect is 0 pixels
 +       there's nothing to do */
 +    if (OutputRect.right <= OutputRect.left ||
 +            OutputRect.bottom <= OutputRect.top)
 +    {
 +        return TRUE;
 +    }
 +
 +    OutputObj = DestObj;
 +
 +    if (BrushOrigin)
 +    {
 +        AdjustedBrushOrigin.x = BrushOrigin->x;
 +        AdjustedBrushOrigin.y = BrushOrigin->y;
 +    }
 +    else
 +    {
 +        AdjustedBrushOrigin.x = 0;
 +        AdjustedBrushOrigin.y = 0;
 +    }
 +
 +    /* Determine clipping type */
 +    if (ClipRegion == (CLIPOBJ *) NULL)
 +    {
 +        clippingType = DC_TRIVIAL;
 +    }
 +    else
 +    {
 +        clippingType = ClipRegion->iDComplexity;
 +    }
 +
-     else if (ROP3_TO_ROP4(PATCOPY) == rop4)
++    /*if (R4_MASK == rop4)
 +    {
 +        BltRectFunc = BltMask;
 +    }
++    else */if (ROP3_TO_ROP4(PATCOPY) == rop4)
 +    {
 +        if (pbo && pbo->iSolidColor == 0xFFFFFFFF)
 +            BltRectFunc = CallDibBitBlt;
 +        else
 +            BltRectFunc = BltPatCopy;
 +    }
 +    else
 +    {
 +        BltRectFunc = CallDibBitBlt;
 +    }
 +
 +
 +    switch (clippingType)
 +    {
 +        case DC_TRIVIAL:
 +            Ret = (*BltRectFunc)(OutputObj, InputObj, Mask, ColorTranslation,
 +                                 &OutputRect, &InputPoint, MaskOrigin, pbo,
 +                                 &AdjustedBrushOrigin, rop4);
 +            break;
 +        case DC_RECT:
 +            /* Clip the blt to the clip rectangle */
 +            ClipRect.left = ClipRegion->rclBounds.left;
 +            ClipRect.right = ClipRegion->rclBounds.right;
 +            ClipRect.top = ClipRegion->rclBounds.top;
 +            ClipRect.bottom = ClipRegion->rclBounds.bottom;
 +            if (RECTL_bIntersectRect(&CombinedRect, &OutputRect, &ClipRect))
 +            {
 +                Pt.x = InputPoint.x + CombinedRect.left - OutputRect.left;
 +                Pt.y = InputPoint.y + CombinedRect.top - OutputRect.top;
 +                Ret = (*BltRectFunc)(OutputObj, InputObj, Mask, ColorTranslation,
 +                                     &CombinedRect, &Pt, MaskOrigin, pbo,
 +                                     &AdjustedBrushOrigin, rop4);
 +            }
 +            break;
 +        case DC_COMPLEX:
 +            Ret = TRUE;
 +            if (OutputObj == InputObj)
 +            {
 +                if (OutputRect.top < InputPoint.y)
 +                {
 +                    Direction = OutputRect.left < InputPoint.x ?
 +                                CD_RIGHTDOWN : CD_LEFTDOWN;
 +                }
 +                else
 +                {
 +                    Direction = OutputRect.left < InputPoint.x ?
 +                                CD_RIGHTUP : CD_LEFTUP;
 +                }
 +            }
 +            else
 +            {
 +                Direction = CD_ANY;
 +            }
 +            CLIPOBJ_cEnumStart(ClipRegion, FALSE, CT_RECTANGLES, Direction, 0);
 +            do
 +            {
 +                EnumMore = CLIPOBJ_bEnum(ClipRegion,(ULONG) sizeof(RectEnum),
 +                                         (PVOID) &RectEnum);
 +
 +                for (i = 0; i < RectEnum.c; i++)
 +                {
 +                    ClipRect.left = RectEnum.arcl[i].left;
 +                    ClipRect.right = RectEnum.arcl[i].right;
 +                    ClipRect.top = RectEnum.arcl[i].top;
 +                    ClipRect.bottom = RectEnum.arcl[i].bottom;
 +                    if (RECTL_bIntersectRect(&CombinedRect, &OutputRect, &ClipRect))
 +                    {
 +                        Pt.x = InputPoint.x + CombinedRect.left - OutputRect.left;
 +                        Pt.y = InputPoint.y + CombinedRect.top - OutputRect.top;
 +                        Ret = (*BltRectFunc)(OutputObj, InputObj, Mask,
 +                                             ColorTranslation, &CombinedRect, &Pt,
 +                                             MaskOrigin, pbo, &AdjustedBrushOrigin,
 +                                             rop4) && Ret;
 +                    }
 +                }
 +            }
 +            while (EnumMore);
 +            break;
 +    }
 +
 +    return Ret;
 +}
 +
 +BOOL APIENTRY
 +IntEngBitBlt(
 +    SURFOBJ *psoTrg,
 +    SURFOBJ *psoSrc,
 +    SURFOBJ *psoMask,
 +    CLIPOBJ *pco,
 +    XLATEOBJ *pxlo,
 +    RECTL *prclTrg,
 +    POINTL *pptlSrc,
 +    POINTL *pptlMask,
 +    BRUSHOBJ *pbo,
 +    POINTL *pptlBrush,
 +    ROP4 rop4)
 +{
 +    SURFACE *psurfTrg;
 +    SURFACE *psurfSrc = NULL;
 +    BOOL bResult;
 +    RECTL rclClipped;
 +    RECTL rclSrc;
 +//    INTENG_ENTER_LEAVE EnterLeaveSource;
 +//    INTENG_ENTER_LEAVE EnterLeaveDest;
 +    PFN_DrvBitBlt pfnBitBlt;
 +
 +    ASSERT(psoTrg);
 +    psurfTrg = CONTAINING_RECORD(psoTrg, SURFACE, SurfObj);
 +
 +    /* FIXME: Should we really allow to pass non-well-ordered rects? */
 +    rclClipped = *prclTrg;
 +    RECTL_vMakeWellOrdered(&rclClipped);
 +
 +    /* Clip target rect against the bounds of the clipping region */
 +    if (pco)
 +    {
 +        if (!RECTL_bIntersectRect(&rclClipped, &rclClipped, &pco->rclBounds))
 +        {
 +            /* Nothing left */
 +            return TRUE;
 +        }
 +
 +        /* Don't pass a clipobj with only a single rect */
 +        if (pco->iDComplexity == DC_RECT)
 +            pco = NULL;
 +    }
 +
 +    if (ROP4_USES_SOURCE(rop4))
 +    {
 +        ASSERT(psoSrc);
 +        psurfSrc = CONTAINING_RECORD(psoSrc, SURFACE, SurfObj);
 +
 +        /* Calculate source rect */
 +        rclSrc.left = pptlSrc->x + rclClipped.left - prclTrg->left;
 +        rclSrc.top = pptlSrc->y + rclClipped.top - prclTrg->top;
 +        rclSrc.right = rclSrc.left + rclClipped.right - rclClipped.left;
 +        rclSrc.bottom = rclSrc.top + rclClipped.bottom - rclClipped.top;
 +    }
 +    else
 +    {
 +        psoSrc = NULL;
 +        psurfSrc = NULL;
 +    }
 +
 +    /* Is the target surface device managed? */
 +    if (psurfTrg->flags & HOOK_BITBLT)
 +    {
 +        /* Is the source a different device managed surface? */
 +        if (psoSrc && psoSrc->hdev != psoTrg->hdev && psurfSrc->flags & HOOK_BITBLT)
 +        {
 +            DPRINT1("Need to copy to standard bitmap format!\n");
 +            ASSERT(FALSE);
 +        }
 +
 +        pfnBitBlt = GDIDEVFUNCS(psoTrg).BitBlt;
 +    }
 +
 +    /* Is the source surface device managed? */
 +    else if (psoSrc && psurfSrc->flags & HOOK_BITBLT)
 +    {
 +        pfnBitBlt = GDIDEVFUNCS(psoSrc).BitBlt;
 +    }
 +    else
 +    {
 +        pfnBitBlt = EngBitBlt;
 +    }
 +
 +    bResult = pfnBitBlt(psoTrg,
 +                        psoSrc,
 +                        psoMask,
 +                        pco,
 +                        pxlo,
 +                        &rclClipped,
 +                        (POINTL*)&rclSrc,
 +                        pptlMask,
 +                        pbo,
 +                        pptlBrush,
 +                        rop4);
 +
 +    // FIXME: cleanup temp surface!
 +
 +    return bResult;
 +}
 +
 +
 +/**** REACTOS FONT RENDERING CODE *********************************************/
 +
 +/* renders the alpha mask bitmap */
 +static BOOLEAN APIENTRY
 +AlphaBltMask(SURFOBJ* psoDest,
 +             SURFOBJ* psoSource, // unused
 +             SURFOBJ* psoMask,
 +             XLATEOBJ* pxloRGB2Dest,
 +             XLATEOBJ* pxloBrush,
 +             RECTL* prclDest,
 +             POINTL* pptlSource, // unused
 +             POINTL* pptlMask,
 +             BRUSHOBJ* pbo,
 +             POINTL* pptlBrush)
 +{
 +    LONG i, j, dx, dy;
 +    int r, g, b;
 +    ULONG Background, BrushColor, NewColor;
 +    BYTE *tMask, *lMask;
 +
 +    ASSERT(psoSource == NULL);
 +    ASSERT(pptlSource == NULL);
 +
 +    dx = prclDest->right  - prclDest->left;
 +    dy = prclDest->bottom - prclDest->top;
 +
 +    if (psoMask != NULL)
 +    {
 +        BrushColor = XLATEOBJ_iXlate(pxloBrush, pbo ? pbo->iSolidColor : 0);
 +        r = (int)GetRValue(BrushColor);
 +        g = (int)GetGValue(BrushColor);
 +        b = (int)GetBValue(BrushColor);
 +
 +        tMask = (PBYTE)psoMask->pvScan0 + (pptlMask->y * psoMask->lDelta) + pptlMask->x;
 +        for (j = 0; j < dy; j++)
 +        {
 +            lMask = tMask;
 +            for (i = 0; i < dx; i++)
 +            {
 +                if (*lMask > 0)
 +                {
 +                    if (*lMask == 0xff)
 +                    {
 +                        DibFunctionsForBitmapFormat[psoDest->iBitmapFormat].DIB_PutPixel(
 +                            psoDest, prclDest->left + i, prclDest->top + j, pbo ? pbo->iSolidColor : 0);
 +                    }
 +                    else
 +                    {
 +                        Background = DIB_GetSource(psoDest, prclDest->left + i, prclDest->top + j,
 +                                                   pxloBrush);
 +
 +                        NewColor =
 +                            RGB((*lMask * (r - GetRValue(Background)) >> 8) + GetRValue(Background),
 +                                (*lMask * (g - GetGValue(Background)) >> 8) + GetGValue(Background),
 +                                (*lMask * (b - GetBValue(Background)) >> 8) + GetBValue(Background));
 +
 +                        Background = XLATEOBJ_iXlate(pxloRGB2Dest, NewColor);
 +                        DibFunctionsForBitmapFormat[psoDest->iBitmapFormat].DIB_PutPixel(
 +                            psoDest, prclDest->left + i, prclDest->top + j, Background);
 +                    }
 +                }
 +                lMask++;
 +            }
 +            tMask += psoMask->lDelta;
 +        }
 +        return TRUE;
 +    }
 +    else
 +    {
 +        return FALSE;
 +    }
 +}
 +
 +static
 +BOOL APIENTRY
 +EngMaskBitBlt(SURFOBJ *psoDest,
 +              SURFOBJ *psoMask,
 +              CLIPOBJ *ClipRegion,
 +              XLATEOBJ *DestColorTranslation,
 +              XLATEOBJ *SourceColorTranslation,
 +              RECTL *DestRect,
 +              POINTL *pptlMask,
 +              BRUSHOBJ *pbo,
 +              POINTL *BrushOrigin)
 +{
 +    BYTE               clippingType;
 +    RECTL              CombinedRect;
 +    RECT_ENUM          RectEnum;
 +    BOOL               EnumMore;
 +    POINTL             InputPoint;
 +    RECTL              InputRect;
 +    RECTL              OutputRect;
 +    POINTL             Translate;
 +    INTENG_ENTER_LEAVE EnterLeaveSource;
 +    INTENG_ENTER_LEAVE EnterLeaveDest;
 +    SURFOBJ*           psoInput;
 +    SURFOBJ*           psoOutput;
 +    BOOLEAN            Ret = TRUE;
 +    RECTL              ClipRect;
 +    unsigned           i;
 +    POINTL             Pt;
 +    ULONG              Direction;
 +    POINTL             AdjustedBrushOrigin;
 +
 +    ASSERT(psoMask);
 +
 +    if (pptlMask)
 +    {
 +        InputRect.left = pptlMask->x;
 +        InputRect.right = pptlMask->x + (DestRect->right - DestRect->left);
 +        InputRect.top = pptlMask->y;
 +        InputRect.bottom = pptlMask->y + (DestRect->bottom - DestRect->top);
 +    }
 +    else
 +    {
 +        InputRect.left = 0;
 +        InputRect.right = DestRect->right - DestRect->left;
 +        InputRect.top = 0;
 +        InputRect.bottom = DestRect->bottom - DestRect->top;
 +    }
 +
 +    OutputRect = *DestRect;
 +    if (NULL != ClipRegion)
 +    {
 +        if (OutputRect.left < ClipRegion->rclBounds.left)
 +        {
 +            InputRect.left += ClipRegion->rclBounds.left - OutputRect.left;
 +            OutputRect.left = ClipRegion->rclBounds.left;
 +        }
 +        if (ClipRegion->rclBounds.right < OutputRect.right)
 +        {
 +            InputRect.right -=  OutputRect.right - ClipRegion->rclBounds.right;
 +            OutputRect.right = ClipRegion->rclBounds.right;
 +        }
 +        if (OutputRect.top < ClipRegion->rclBounds.top)
 +        {
 +            InputRect.top += ClipRegion->rclBounds.top - OutputRect.top;
 +            OutputRect.top = ClipRegion->rclBounds.top;
 +        }
 +        if (ClipRegion->rclBounds.bottom < OutputRect.bottom)
 +        {
 +            InputRect.bottom -=  OutputRect.bottom - ClipRegion->rclBounds.bottom;
 +            OutputRect.bottom = ClipRegion->rclBounds.bottom;
 +        }
 +    }
 +
 +    if (! IntEngEnter(&EnterLeaveSource, psoMask, &InputRect, TRUE, &Translate, &psoInput))
 +    {
 +        return FALSE;
 +    }
 +
 +    InputPoint.x = InputRect.left + Translate.x;
 +    InputPoint.y = InputRect.top + Translate.y;
 +
 +    /* Check for degenerate case: if height or width of OutputRect is 0 pixels there's
 +       nothing to do */
 +    if (OutputRect.right <= OutputRect.left || OutputRect.bottom <= OutputRect.top)
 +    {
 +        IntEngLeave(&EnterLeaveSource);
 +        return TRUE;
 +    }
 +
 +    if (! IntEngEnter(&EnterLeaveDest, psoDest, &OutputRect, FALSE, &Translate, &psoOutput))
 +    {
 +        IntEngLeave(&EnterLeaveSource);
 +        return FALSE;
 +    }
 +
 +    OutputRect.left = DestRect->left + Translate.x;
 +    OutputRect.right = DestRect->right + Translate.x;
 +    OutputRect.top = DestRect->top + Translate.y;
 +    OutputRect.bottom = DestRect->bottom + Translate.y;
 +
 +    if (BrushOrigin)
 +    {
 +        AdjustedBrushOrigin.x = BrushOrigin->x + Translate.x;
 +        AdjustedBrushOrigin.y = BrushOrigin->y + Translate.y;
 +    }
 +    else
 +        AdjustedBrushOrigin = Translate;
 +
 +    // Determine clipping type
 +    if (ClipRegion == (CLIPOBJ *) NULL)
 +    {
 +        clippingType = DC_TRIVIAL;
 +    } else {
 +        clippingType = ClipRegion->iDComplexity;
 +    }
 +
 +    switch (clippingType)
 +    {
 +        case DC_TRIVIAL:
 +            if (psoMask->iBitmapFormat == BMF_8BPP)
 +                Ret = AlphaBltMask(psoOutput, NULL , psoInput, DestColorTranslation, SourceColorTranslation,
 +                                   &OutputRect, NULL, &InputPoint, pbo, &AdjustedBrushOrigin);
 +            else
 +                Ret = BltMask(psoOutput, NULL, psoInput, DestColorTranslation,
 +                              &OutputRect, NULL, &InputPoint, pbo, &AdjustedBrushOrigin,
 +                              R4_MASK);
 +            break;
 +        case DC_RECT:
 +            // Clip the blt to the clip rectangle
 +            ClipRect.left = ClipRegion->rclBounds.left + Translate.x;
 +            ClipRect.right = ClipRegion->rclBounds.right + Translate.x;
 +            ClipRect.top = ClipRegion->rclBounds.top + Translate.y;
 +            ClipRect.bottom = ClipRegion->rclBounds.bottom + Translate.y;
 +            if (RECTL_bIntersectRect(&CombinedRect, &OutputRect, &ClipRect))
 +            {
 +                Pt.x = InputPoint.x + CombinedRect.left - OutputRect.left;
 +                Pt.y = InputPoint.y + CombinedRect.top - OutputRect.top;
 +                if (psoMask->iBitmapFormat == BMF_8BPP)
 +                {
 +                    Ret = AlphaBltMask(psoOutput, NULL, psoInput, DestColorTranslation, SourceColorTranslation,
 +                                       &CombinedRect, NULL, &Pt, pbo, &AdjustedBrushOrigin);
 +                }
 +                else
 +                {
 +                    Ret = BltMask(psoOutput, NULL, psoInput, DestColorTranslation,
 +                                  &CombinedRect, NULL, &Pt, pbo, &AdjustedBrushOrigin, R4_MASK);
 +                }
 +            }
 +            break;
 +        case DC_COMPLEX:
 +            Ret = TRUE;
 +            if (psoOutput == psoInput)
 +            {
 +                if (OutputRect.top < InputPoint.y)
 +                {
 +                    Direction = OutputRect.left < InputPoint.x ? CD_RIGHTDOWN : CD_LEFTDOWN;
 +                }
 +                else
 +                {
 +                    Direction = OutputRect.left < InputPoint.x ? CD_RIGHTUP : CD_LEFTUP;
 +                }
 +            }
 +            else
 +            {
 +                Direction = CD_ANY;
 +            }
 +            CLIPOBJ_cEnumStart(ClipRegion, FALSE, CT_RECTANGLES, Direction, 0);
 +            do
 +            {
 +                EnumMore = CLIPOBJ_bEnum(ClipRegion,(ULONG) sizeof(RectEnum), (PVOID) &RectEnum);
 +
 +                for (i = 0; i < RectEnum.c; i++)
 +                {
 +                    ClipRect.left = RectEnum.arcl[i].left + Translate.x;
 +                    ClipRect.right = RectEnum.arcl[i].right + Translate.x;
 +                    ClipRect.top = RectEnum.arcl[i].top + Translate.y;
 +                    ClipRect.bottom = RectEnum.arcl[i].bottom + Translate.y;
 +                    if (RECTL_bIntersectRect(&CombinedRect, &OutputRect, &ClipRect))
 +                    {
 +                        Pt.x = InputPoint.x + CombinedRect.left - OutputRect.left;
 +                        Pt.y = InputPoint.y + CombinedRect.top - OutputRect.top;
 +                        if (psoMask->iBitmapFormat == BMF_8BPP)
 +                        {
 +                            Ret = AlphaBltMask(psoOutput, NULL, psoInput,
 +                                               DestColorTranslation,
 +                                               SourceColorTranslation,
 +                                               &CombinedRect, NULL, &Pt, pbo,
 +                                               &AdjustedBrushOrigin) && Ret;
 +                        }
 +                        else
 +                        {
 +                            Ret = BltMask(psoOutput, NULL, psoInput,
 +                                          DestColorTranslation, &CombinedRect, NULL,
 +                                          &Pt, pbo, &AdjustedBrushOrigin,
 +                                          R4_MASK) && Ret;
 +                        }
 +                    }
 +                }
 +            }
 +            while (EnumMore);
 +            break;
 +    }
 +
 +
 +    IntEngLeave(&EnterLeaveDest);
 +    IntEngLeave(&EnterLeaveSource);
 +
 +    return Ret;
 +}
 +
 +BOOL APIENTRY
 +IntEngMaskBlt(SURFOBJ *psoDest,
 +              SURFOBJ *psoMask,
 +              CLIPOBJ *ClipRegion,
 +              XLATEOBJ *DestColorTranslation,
 +              XLATEOBJ *SourceColorTranslation,
 +              RECTL *DestRect,
 +              POINTL *pptlMask,
 +              BRUSHOBJ *pbo,
 +              POINTL *BrushOrigin)
 +{
 +    BOOLEAN ret;
 +    RECTL OutputRect;
 +    POINTL InputPoint;
 +    SURFACE *psurfDest;
 +
 +    ASSERT(psoMask);
 +
 +    if (pptlMask)
 +    {
 +        InputPoint = *pptlMask;
 +    }
 +
 +    /* Clip against the bounds of the clipping region so we won't try to write
 +     * outside the surface */
 +    if (NULL != ClipRegion)
 +    {
 +        if (!RECTL_bIntersectRect(&OutputRect, DestRect, &ClipRegion->rclBounds))
 +        {
 +            return TRUE;
 +        }
 +        InputPoint.x += OutputRect.left - DestRect->left;
 +        InputPoint.y += OutputRect.top - DestRect->top;
 +    }
 +    else
 +    {
 +        OutputRect = *DestRect;
 +    }
 +
 +    /* No success yet */
 +    ret = FALSE;
 +    ASSERT(psoDest);
 +    psurfDest = CONTAINING_RECORD(psoDest, SURFACE, SurfObj);
 +
 +    /* Dummy BitBlt to let driver know that it should flush its changes.
 +       This should really be done using a call to DrvSynchronizeSurface,
 +       but the VMware driver doesn't hook that call. */
 +    IntEngBitBlt(psoDest, NULL, psoMask, ClipRegion, DestColorTranslation,
 +                   DestRect, pptlMask, pptlMask, pbo, BrushOrigin,
 +                   R4_NOOP);
 +
 +    ret = EngMaskBitBlt(psoDest, psoMask, ClipRegion, DestColorTranslation, SourceColorTranslation,
 +                        &OutputRect, &InputPoint, pbo, BrushOrigin);
 +
 +    /* Dummy BitBlt to let driver know that something has changed. */
 +    IntEngBitBlt(psoDest, NULL, psoMask, ClipRegion, DestColorTranslation,
 +                   DestRect, pptlMask, pptlMask, pbo, BrushOrigin,
 +                   R4_NOOP);
 +
 +    return ret;
 +}
 +
 +/* EOF */
index 18d2f24,0000000..3b6cd04
mode 100644,000000..100644
--- /dev/null
@@@ -1,51 -1,0 +1,53 @@@
 + /*
 + * COPYRIGHT:         See COPYING in the top level directory
 + * PROJECT:           ReactOS kernel
 + * PURPOSE:           XLATEOBJ structures and functions
 + * FILE:              subsystem/win32/win32k/eng/objects.h
 + * PROGRAMER:         Timo Kreuzer
 + *
 + */
 +
 +#include <include/palette.h>
 +
 +struct _EXLATEOBJ;
 +
 +typedef ULONG (FASTCALL *PFN_XLATE)(struct _EXLATEOBJ *pexlo, ULONG iColor);
 +
 +typedef struct _EXLATEOBJ
 +{
 +    XLATEOBJ xlo;
 +
 +    PFN_XLATE pfnXlate;
 +
 +    PPALETTE ppalSrc;
 +    PPALETTE ppalDst;
 +    PPALETTE ppalDstDc;
 +
 +    HANDLE hColorTransform;
 +
 +    union
 +    {
 +        ULONG aulXlate[6];
 +        struct
 +        {
 +            ULONG ulRedMask;
 +            ULONG ulGreenMask;
 +            ULONG ulBlueMask;
 +            ULONG ulRedShift;
 +            ULONG ulGreenShift;
 +            ULONG ulBlueShift;
 +        };
 +    };
 +} EXLATEOBJ, *PEXLATEOBJ;
 +
 +void
 +DbgCmpXlate(XLATEOBJ *pxlo1, XLATEOBJ *pxlo2);
 +
 +VOID NTAPI EXLATEOBJ_vInitialize(PEXLATEOBJ pexlo, PALETTE *ppalSrc, PALETTE *ppalDst, ULONG, ULONG, ULONG);
 +VOID NTAPI EXLATEOBJ_vInitXlateFromDCs(PEXLATEOBJ pexlo, PDC pdcSrc, PDC pdcDst);
 +VOID NTAPI EXLATEOBJ_vInitSrcMonoXlate(PEXLATEOBJ pexlo, PPALETTE ppalDst, ULONG Color0, ULONG Color1);
 +VOID NTAPI EXLATEOBJ_vCleanup(PEXLATEOBJ pexlo);
 +
++extern XLATEOBJ* gpxloTrivial;
++
 +//#define XLATEOBJ_iXlate(pxo, Color) ((EXLATEOBJ*)pxo)->pfnXlate(pxo, Color)
index 917b142,0000000..4b0fa99
mode 100644,000000..100644
--- /dev/null
@@@ -1,1514 -1,0 +1,1587 @@@
- #define NDEBUG
 +/*
 + *  ReactOS W32 Subsystem
 + *  Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
 + *
 + *  This program is free software; you can redistribute it and/or modify
 + *  it under the terms of the GNU General Public License as published by
 + *  the Free Software Foundation; either version 2 of the License, or
 + *  (at your option) any later version.
 + *
 + *  This program is distributed in the hope that it will be useful,
 + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 + *  GNU General Public License for more details.
 + *
 + *  You should have received a copy of the GNU General Public License along
 + *  with this program; if not, write to the Free Software Foundation, Inc.,
 + *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 + */
 +
 +/*
 + * We handle two types of cursors/icons:
 + * - Private
 + *   Loaded without LR_SHARED flag
 + *   Private to a process
 + *   Can be deleted by calling NtDestroyCursorIcon()
 + *   CurIcon->hModule, CurIcon->hRsrc and CurIcon->hGroupRsrc set to NULL
 + * - Shared
 + *   Loaded with LR_SHARED flag
 + *   Possibly shared by multiple processes
 + *   Immune to NtDestroyCursorIcon()
 + *   CurIcon->hModule, CurIcon->hRsrc and CurIcon->hGroupRsrc are valid
 + * There's a M:N relationship between processes and (shared) cursor/icons.
 + * A process can have multiple cursor/icons and a cursor/icon can be used
 + * by multiple processes. To keep track of this we keep a list of all
 + * cursor/icons (CurIconList) and per cursor/icon we keep a list of
 + * CURICON_PROCESS structs starting at CurIcon->ProcessList.
 + */
 +
 +#include <win32k.h>
 +
-     BOOL Ret = FALSE;
-     HBITMAP hbmMask, hbmColor;
-     BITMAP bmpColor, bm;
++//#define NDEBUG
 +#include <debug.h>
 +
 +static PAGED_LOOKASIDE_LIST gProcessLookasideList;
 +static LIST_ENTRY gCurIconList;
 +
 +SYSTEM_CURSORINFO gSysCursorInfo;
 +
 +BOOL
 +InitCursorImpl()
 +{
 +    ExInitializePagedLookasideList(&gProcessLookasideList,
 +                                   NULL,
 +                                   NULL,
 +                                   0,
 +                                   sizeof(CURICON_PROCESS),
 +                                   TAG_DIB,
 +                                   128);
 +    InitializeListHead(&gCurIconList);
 +
 +     gSysCursorInfo.Enabled = FALSE;
 +     gSysCursorInfo.ButtonsDown = 0;
 +     gSysCursorInfo.CursorClipInfo.IsClipped = FALSE;
 +     gSysCursorInfo.LastBtnDown = 0;
 +     gSysCursorInfo.CurrentCursorObject = NULL;
 +     gSysCursorInfo.ShowingCursor = 0;
 +     gSysCursorInfo.ClickLockActive = FALSE;
 +     gSysCursorInfo.ClickLockTime = 0;
 +
 +    return TRUE;
 +}
 +
 +PSYSTEM_CURSORINFO
 +IntGetSysCursorInfo()
 +{
 +    return &gSysCursorInfo;
 +}
 +
 +/* This function creates a reference for the object! */
 +PCURICON_OBJECT FASTCALL UserGetCurIconObject(HCURSOR hCurIcon)
 +{
 +    PCURICON_OBJECT CurIcon;
 +
 +    if (!hCurIcon)
 +    {
 +        SetLastWin32Error(ERROR_INVALID_CURSOR_HANDLE);
 +        return NULL;
 +    }
 +
 +    CurIcon = (PCURICON_OBJECT)UserReferenceObjectByHandle(hCurIcon, otCursorIcon);
 +    if (!CurIcon)
 +    {
 +        /* we never set ERROR_INVALID_ICON_HANDLE. lets hope noone ever checks for it */
 +        SetLastWin32Error(ERROR_INVALID_CURSOR_HANDLE);
 +        return NULL;
 +    }
 +
 +    ASSERT(CurIcon->head.cLockObj >= 1);
 +    return CurIcon;
 +}
 +
 +HCURSOR
 +FASTCALL
 +UserSetCursor(
 +    PCURICON_OBJECT NewCursor,
 +    BOOL ForceChange)
 +{
 +    PSYSTEM_CURSORINFO CurInfo;
 +    PCURICON_OBJECT OldCursor;
 +    HCURSOR hOldCursor = (HCURSOR)0;
 +    HDC hdcScreen;
 +    BOOL bResult;
 +
 +      CurInfo = IntGetSysCursorInfo();
 +
 +    OldCursor = CurInfo->CurrentCursorObject;
 +    if (OldCursor)
 +    {
 +        hOldCursor = (HCURSOR)OldCursor->Self;
 +    }
 +
 +    /* Is the new cursor the same as the old cursor? */
 +    if (OldCursor == NewCursor)
 +    {
 +        /* Nothing to to do in this case */
 +        return hOldCursor;
 +    }
 +
 +    /* Get the screen DC */
 +    if(!(hdcScreen = IntGetScreenDC()))
 +    {
 +        return (HCURSOR)0;
 +    }
 +
 +    /* Do we have a new cursor? */
 +    if (NewCursor)
 +    {
 +        UserReferenceObject(NewCursor);
 +
 +        CurInfo->ShowingCursor = 1;
 +        CurInfo->CurrentCursorObject = NewCursor;
 +
 +        /* Call GDI to set the new screen cursor */
 +        bResult = GreSetPointerShape(hdcScreen,
 +                                     NewCursor->IconInfo.hbmMask,
 +                                     NewCursor->IconInfo.hbmColor,
 +                                     NewCursor->IconInfo.xHotspot,
 +                                     NewCursor->IconInfo.yHotspot,
 +                                     gpsi->ptCursor.x,
 +                                     gpsi->ptCursor.y);
 +
 +
 +    }
 +    else
 +    {
 +        /* Check if were diplaying a cursor */
 +        if (OldCursor && CurInfo->ShowingCursor)
 +        {
 +            /* Remove the cursor */
 +            GreMovePointer(hdcScreen, -1, -1);
 +            DPRINT("Removing pointer!\n");
 +        }
 +
 +        CurInfo->CurrentCursorObject = NULL;
 +        CurInfo->ShowingCursor = 0;
 +    }
 +
 +    /* OldCursor is not in use anymore */
 +    if (OldCursor)
 +    {
 +        UserDereferenceObject(OldCursor);
 +    }
 +
 +    /* Return handle of the old cursor */
 +    return hOldCursor;
 +}
 +
 +BOOL UserSetCursorPos( INT x, INT y, BOOL SendMouseMoveMsg)
 +{
 +    PWINDOW_OBJECT DesktopWindow;
 +    PSYSTEM_CURSORINFO CurInfo;
 +    HDC hDC;
 +    MSG Msg;
 +
 +    if(!(hDC = IntGetScreenDC()))
 +    {
 +        return FALSE;
 +    }
 +
 +    CurInfo = IntGetSysCursorInfo();
 +
 +    DesktopWindow = UserGetDesktopWindow();
 +
 +    if (DesktopWindow)
 +    {
 +        if(x >= DesktopWindow->Wnd->rcClient.right)
 +            x = DesktopWindow->Wnd->rcClient.right - 1;
 +        if(y >= DesktopWindow->Wnd->rcClient.bottom)
 +            y = DesktopWindow->Wnd->rcClient.bottom - 1;
 +    }
 +
 +    if(x < 0)
 +        x = 0;
 +    if(y < 0)
 +        y = 0;
 +
 +    //Clip cursor position
 +    if(CurInfo->CursorClipInfo.IsClipped)
 +    {
 +       if(x >= (LONG)CurInfo->CursorClipInfo.Right)
 +           x = (LONG)CurInfo->CursorClipInfo.Right - 1;
 +       if(x < (LONG)CurInfo->CursorClipInfo.Left)
 +           x = (LONG)CurInfo->CursorClipInfo.Left;
 +       if(y >= (LONG)CurInfo->CursorClipInfo.Bottom)
 +           y = (LONG)CurInfo->CursorClipInfo.Bottom - 1;
 +       if(y < (LONG)CurInfo->CursorClipInfo.Top)
 +           y = (LONG)CurInfo->CursorClipInfo.Top;
 +    }
 +
 +    //Store the new cursor position
 +    gpsi->ptCursor.x = x;
 +    gpsi->ptCursor.y = y;
 +
 +    //Move the mouse pointer
 +    GreMovePointer(hDC, x, y);
 +
 +    if (!SendMouseMoveMsg)
 +       return TRUE;
 +
 +    //Generate a mouse move message
 +    Msg.message = WM_MOUSEMOVE;
 +    Msg.wParam = CurInfo->ButtonsDown;
 +    Msg.lParam = MAKELPARAM(x, y);
 +    Msg.pt = gpsi->ptCursor;
 +    MsqInsertSystemMessage(&Msg);
 +
 +    return TRUE;
 +}
 +
 +/* Called from NtUserCallOneParam with Routine ONEPARAM_ROUTINE_SHOWCURSOR
 + * User32 macro NtUserShowCursor */
 +int UserShowCursor(BOOL bShow)
 +{
 +    PSYSTEM_CURSORINFO CurInfo = IntGetSysCursorInfo();
 +    HDC hdcScreen;
 +
 +    if (!(hdcScreen = IntGetScreenDC()))
 +    {
 +        return 0; /* No mouse */
 +    }
 +
 +    if (bShow == FALSE)
 +    {
 +        /* Check if were diplaying a cursor */
 +        if (CurInfo->ShowingCursor == 1)
 +        {
 +            /* Remove the pointer */
 +            GreMovePointer(hdcScreen, -1, -1);
 +            DPRINT("Removing pointer!\n");
 +        }
 +        CurInfo->ShowingCursor--;
 +    }
 +    else
 +    {
 +        if (CurInfo->ShowingCursor == 0)
 +        {
 +            /*Show the pointer*/
 +            GreMovePointer(hdcScreen, gpsi->ptCursor.x, gpsi->ptCursor.y);
 +        }
 +        CurInfo->ShowingCursor++;
 +    }
 +
 +    return CurInfo->ShowingCursor;
 +}
 +
 +/*
 + * We have to register that this object is in use by the current
 + * process. The only way to do that seems to be to walk the list
 + * of cursor/icon objects starting at W32Process->CursorIconListHead.
 + * If the object is already present in the list, we don't have to do
 + * anything, if it's not present we add it and inc the ProcessCount
 + * in the object. Having to walk the list kind of sucks, but that's
 + * life...
 + */
 +static BOOLEAN FASTCALL
 +ReferenceCurIconByProcess(PCURICON_OBJECT CurIcon)
 +{
 +    PPROCESSINFO Win32Process;
 +    PCURICON_PROCESS Current;
 +
 +    Win32Process = PsGetCurrentProcessWin32Process();
 +
 +    LIST_FOR_EACH(Current, &CurIcon->ProcessList, CURICON_PROCESS, ListEntry)
 +    {
 +        if (Current->Process == Win32Process)
 +        {
 +            /* Already registered for this process */
 +            return TRUE;
 +        }
 +    }
 +
 +    /* Not registered yet */
 +    Current = ExAllocateFromPagedLookasideList(&gProcessLookasideList);
 +    if (NULL == Current)
 +    {
 +        return FALSE;
 +    }
 +    InsertHeadList(&CurIcon->ProcessList, &Current->ListEntry);
 +    Current->Process = Win32Process;
 +
 +    return TRUE;
 +}
 +
 +PCURICON_OBJECT FASTCALL
 +IntFindExistingCurIconObject(HMODULE hModule,
 +                             HRSRC hRsrc, LONG cx, LONG cy)
 +{
 +    PCURICON_OBJECT CurIcon;
 +
 +    LIST_FOR_EACH(CurIcon, &gCurIconList, CURICON_OBJECT, ListEntry)
 +    {
 +
 +        //    if(NT_SUCCESS(UserReferenceObjectByPointer(Object, otCursorIcon))) //<- huh????
 +//      UserReferenceObject(  CurIcon);
 +//      {
 +        if ((CurIcon->hModule == hModule) && (CurIcon->hRsrc == hRsrc))
 +        {
 +            if (cx && ((cx != CurIcon->Size.cx) || (cy != CurIcon->Size.cy)))
 +            {
 +//               UserDereferenceObject(CurIcon);
 +                continue;
 +            }
 +            if (! ReferenceCurIconByProcess(CurIcon))
 +            {
 +                return NULL;
 +            }
 +
 +            return CurIcon;
 +        }
 +//      }
 +//      UserDereferenceObject(CurIcon);
 +
 +    }
 +
 +    return NULL;
 +}
 +
 +PCURICON_OBJECT
 +IntCreateCurIconHandle()
 +{
 +    PCURICON_OBJECT CurIcon;
 +    HANDLE hCurIcon;
 +
 +    CurIcon = UserCreateObject(gHandleTable, NULL, &hCurIcon, otCursorIcon, sizeof(CURICON_OBJECT));
 +
 +    if (!CurIcon)
 +    {
 +        SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
 +        return FALSE;
 +    }
 +
 +    CurIcon->Self = hCurIcon;
 +    InitializeListHead(&CurIcon->ProcessList);
 +
 +    if (! ReferenceCurIconByProcess(CurIcon))
 +    {
 +        DPRINT1("Failed to add process\n");
 +        UserDeleteObject(hCurIcon, otCursorIcon);
 +        UserDereferenceObject(CurIcon);
 +        return NULL;
 +    }
 +
 +    InsertHeadList(&gCurIconList, &CurIcon->ListEntry);
 +
 +    return CurIcon;
 +}
 +
 +BOOLEAN FASTCALL
 +IntDestroyCurIconObject(PCURICON_OBJECT CurIcon, BOOL ProcessCleanup)
 +{
 +    PSYSTEM_CURSORINFO CurInfo;
 +    HBITMAP bmpMask, bmpColor;
 +    BOOLEAN Ret;
 +    PCURICON_PROCESS Current = NULL;
 +    PPROCESSINFO W32Process = PsGetCurrentProcessWin32Process();
 +
 +    /* Private objects can only be destroyed by their own process */
 +    if (NULL == CurIcon->hModule)
 +    {
 +        ASSERT(CurIcon->ProcessList.Flink->Flink == &CurIcon->ProcessList);
 +        Current = CONTAINING_RECORD(CurIcon->ProcessList.Flink, CURICON_PROCESS, ListEntry);
 +        if (Current->Process != W32Process)
 +        {
 +            DPRINT1("Trying to destroy private icon/cursor of another process\n");
 +            return FALSE;
 +        }
 +    }
 +    else if (! ProcessCleanup)
 +    {
 +        DPRINT("Trying to destroy shared icon/cursor\n");
 +        return FALSE;
 +    }
 +
 +    /* Now find this process in the list of processes referencing this object and
 +       remove it from that list */
 +    LIST_FOR_EACH(Current, &CurIcon->ProcessList, CURICON_PROCESS, ListEntry)
 +    {
 +        if (Current->Process == W32Process)
 +        {
 +            RemoveEntryList(&Current->ListEntry);
 +            break;
 +        }
 +    }
 +
 +    ExFreeToPagedLookasideList(&gProcessLookasideList, Current);
 +
 +    /* If there are still processes referencing this object we can't destroy it yet */
 +    if (! IsListEmpty(&CurIcon->ProcessList))
 +    {
 +        return TRUE;
 +    }
 +
 +
 +    if (! ProcessCleanup)
 +    {
 +        RemoveEntryList(&CurIcon->ListEntry);
 +    }
 +
 +    CurInfo = IntGetSysCursorInfo();
 +
 +    if (CurInfo->CurrentCursorObject == CurIcon)
 +    {
 +        /* Hide the cursor if we're destroying the current cursor */
 +        UserSetCursor(NULL, TRUE);
 +    }
 +
 +    bmpMask = CurIcon->IconInfo.hbmMask;
 +    bmpColor = CurIcon->IconInfo.hbmColor;
 +
 +    /* delete bitmaps */
 +    if (bmpMask)
 +    {
 +        GDIOBJ_SetOwnership(bmpMask, PsGetCurrentProcess());
 +        GreDeleteObject(bmpMask);
 +        CurIcon->IconInfo.hbmMask = NULL;
 +    }
 +    if (bmpColor)
 +    {
 +        GDIOBJ_SetOwnership(bmpColor, PsGetCurrentProcess());
 +        GreDeleteObject(bmpColor);
 +        CurIcon->IconInfo.hbmColor = NULL;
 +    }
 +
 +    /* We were given a pointer, no need to keep the reference anylonger! */
 +    UserDereferenceObject(CurIcon);
 +    Ret = UserDeleteObject(CurIcon->Self, otCursorIcon);
 +
 +    return Ret;
 +}
 +
 +VOID FASTCALL
 +IntCleanupCurIcons(struct _EPROCESS *Process, PPROCESSINFO Win32Process)
 +{
 +    PCURICON_OBJECT CurIcon, tmp;
 +    PCURICON_PROCESS ProcessData;
 +
 +    LIST_FOR_EACH_SAFE(CurIcon, tmp, &gCurIconList, CURICON_OBJECT, ListEntry)
 +    {
 +        UserReferenceObject(CurIcon);
 +        //    if(NT_SUCCESS(UserReferenceObjectByPointer(Object, otCursorIcon)))
 +        {
 +            LIST_FOR_EACH(ProcessData, &CurIcon->ProcessList, CURICON_PROCESS, ListEntry)
 +            {
 +                if (Win32Process == ProcessData->Process)
 +                {
 +                    RemoveEntryList(&CurIcon->ListEntry);
 +                    IntDestroyCurIconObject(CurIcon, TRUE);
 +                    CurIcon = NULL;
 +                    break;
 +                }
 +            }
 +
 +//         UserDereferenceObject(Object);
 +        }
 +
 +        if (CurIcon)
 +        {
 +            UserDereferenceObject(CurIcon);
 +        }
 +    }
 +
 +}
 +
 +
 +/*
 + * @implemented
 + */
 +BOOL
 +APIENTRY
 +NtUserGetIconInfo(
 +    HANDLE hCurIcon,
 +    PICONINFO IconInfo,
 +    PUNICODE_STRING lpInstName, // optional
 +    PUNICODE_STRING lpResName,  // optional
 +    LPDWORD pbpp,               // optional
 +    BOOL bInternal)
 +{
 +    ICONINFO ii;
 +    PCURICON_OBJECT CurIcon;
 +    NTSTATUS Status = STATUS_SUCCESS;
 +    BOOL Ret = FALSE;
 +    DWORD colorBpp = 0;
 +
 +    DPRINT("Enter NtUserGetIconInfo\n");
 +    UserEnterExclusive();
 +
 +    if (!IconInfo)
 +    {
 +        SetLastWin32Error(ERROR_INVALID_PARAMETER);
 +        goto leave;
 +    }
 +
 +    if (!(CurIcon = UserGetCurIconObject(hCurIcon)))
 +    {
 +        goto leave;
 +    }
 +
 +    RtlCopyMemory(&ii, &CurIcon->IconInfo, sizeof(ICONINFO));
 +
 +    /* Copy bitmaps */
 +    ii.hbmMask = BITMAP_CopyBitmap(CurIcon->IconInfo.hbmMask);
 +    ii.hbmColor = BITMAP_CopyBitmap(CurIcon->IconInfo.hbmColor);
 +
 +    if (pbpp)
 +    {
 +        PSURFACE psurfBmp;
 +
 +        psurfBmp = SURFACE_LockSurface(CurIcon->IconInfo.hbmColor);
 +        if (psurfBmp)
 +        {
 +            colorBpp = BitsPerFormat(psurfBmp->SurfObj.iBitmapFormat);
 +            SURFACE_UnlockSurface(psurfBmp);
 +        }
 +    }
 +
 +    /* Copy fields */
 +    _SEH2_TRY
 +    {
 +        ProbeForWrite(IconInfo, sizeof(ICONINFO), 1);
 +        RtlCopyMemory(IconInfo, &ii, sizeof(ICONINFO));
 +
 +        if (pbpp)
 +        {
 +            ProbeForWrite(pbpp, sizeof(DWORD), 1);
 +            *pbpp = colorBpp;
 +        }
 +    }
 +    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
 +    {
 +        Status = _SEH2_GetExceptionCode();
 +    }
 +    _SEH2_END
 +
 +    if (NT_SUCCESS(Status))
 +        Ret = TRUE;
 +    else
 +        SetLastNtError(Status);
 +
 +    UserDereferenceObject(CurIcon);
 +
 +leave:
 +    DPRINT("Leave NtUserGetIconInfo, ret=%i\n", Ret);
 +    UserLeave();
 +
 +    return Ret;
 +}
 +
 +
 +/*
 + * @implemented
 + */
 +BOOL
 +APIENTRY
 +NtUserGetIconSize(
 +    HANDLE hCurIcon,
 +    UINT istepIfAniCur,
 +    PLONG plcx,       // &size.cx
 +    PLONG plcy)       // &size.cy
 +{
 +    PCURICON_OBJECT CurIcon;
 +    NTSTATUS Status = STATUS_SUCCESS;
 +    BOOL bRet = FALSE;
 +
 +    DPRINT("Enter NtUserGetIconSize\n");
 +    UserEnterExclusive();
 +
 +    if (!(CurIcon = UserGetCurIconObject(hCurIcon)))
 +    {
 +        goto cleanup;
 +    }
 +
 +    _SEH2_TRY
 +    {
 +        ProbeForWrite(plcx, sizeof(LONG), 1);
 +        RtlCopyMemory(plcx, &CurIcon->Size.cx, sizeof(LONG));
 +        ProbeForWrite(plcy, sizeof(LONG), 1);
 +        RtlCopyMemory(plcy, &CurIcon->Size.cy, sizeof(LONG));
 +    }
 +    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
 +    {
 +        Status = _SEH2_GetExceptionCode();
 +    }
 +    _SEH2_END
 +
 +    if (NT_SUCCESS(Status))
 +        bRet = TRUE;
 +    else
 +        SetLastNtError(Status); // maybe not, test this
 +
 +    UserDereferenceObject(CurIcon);
 +
 +cleanup:
 +    DPRINT("Leave NtUserGetIconSize, ret=%i\n", bRet);
 +    UserLeave();
 +    return bRet;
 +}
 +
 +
 +/*
 + * @unimplemented
 + */
 +DWORD
 +APIENTRY
 +NtUserGetCursorFrameInfo(
 +    DWORD Unknown0,
 +    DWORD Unknown1,
 +    DWORD Unknown2,
 +    DWORD Unknown3)
 +{
 +    UNIMPLEMENTED
 +
 +    return 0;
 +}
 +
 +
 +/*
 + * @implemented
 + */
 +BOOL
 +APIENTRY
 +NtUserGetCursorInfo(
 +    PCURSORINFO pci)
 +{
 +    CURSORINFO SafeCi;
 +    PSYSTEM_CURSORINFO CurInfo;
 +    NTSTATUS Status = STATUS_SUCCESS;
 +    PCURICON_OBJECT CurIcon;
 +    BOOL Ret = FALSE;
 +    DECLARE_RETURN(BOOL);
 +
 +    DPRINT("Enter NtUserGetCursorInfo\n");
 +    UserEnterExclusive();
 +
 +    CurInfo = IntGetSysCursorInfo();
 +    CurIcon = (PCURICON_OBJECT)CurInfo->CurrentCursorObject;
 +
 +    SafeCi.cbSize = sizeof(CURSORINFO);
 +    SafeCi.flags = ((CurInfo->ShowingCursor && CurIcon) ? CURSOR_SHOWING : 0);
 +    SafeCi.hCursor = (CurIcon ? (HCURSOR)CurIcon->Self : (HCURSOR)0);
 +
 +    SafeCi.ptScreenPos = gpsi->ptCursor;
 +
 +    _SEH2_TRY
 +    {
 +        if (pci->cbSize == sizeof(CURSORINFO))
 +        {
 +            ProbeForWrite(pci, sizeof(CURSORINFO), 1);
 +            RtlCopyMemory(pci, &SafeCi, sizeof(CURSORINFO));
 +            Ret = TRUE;
 +        }
 +        else
 +        {
 +            SetLastWin32Error(ERROR_INVALID_PARAMETER);
 +        }
 +    }
 +    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
 +    {
 +        Status = _SEH2_GetExceptionCode();
 +    }
 +    _SEH2_END;
 +    if (!NT_SUCCESS(Status))
 +    {
 +        SetLastNtError(Status);
 +    }
 +
 +    RETURN(Ret);
 +
 +CLEANUP:
 +    DPRINT("Leave NtUserGetCursorInfo, ret=%i\n",_ret_);
 +    UserLeave();
 +    END_CLEANUP;
 +}
 +
 +BOOL
 +APIENTRY
 +UserClipCursor(
 +    RECTL *prcl)
 +{
 +    /* FIXME - check if process has WINSTA_WRITEATTRIBUTES */
 +    PSYSTEM_CURSORINFO CurInfo;
 +    PWINDOW_OBJECT DesktopWindow = NULL;
 +
 +    CurInfo = IntGetSysCursorInfo();
 +
 +    DesktopWindow = UserGetDesktopWindow();
 +
 +    if (prcl != NULL &&
 +       (prcl->right > prcl->left) &&
 +       (prcl->bottom > prcl->top) &&
 +        DesktopWindow != NULL)
 +    {
 +        CurInfo->CursorClipInfo.IsClipped = TRUE;
 +        CurInfo->CursorClipInfo.Left = max(prcl->left, DesktopWindow->Wnd->rcWindow.left);
 +        CurInfo->CursorClipInfo.Top = max(prcl->top, DesktopWindow->Wnd->rcWindow.top);
 +        CurInfo->CursorClipInfo.Right = min(prcl->right, DesktopWindow->Wnd->rcWindow.right);
 +        CurInfo->CursorClipInfo.Bottom = min(prcl->bottom, DesktopWindow->Wnd->rcWindow.bottom);
 +
 +        UserSetCursorPos(gpsi->ptCursor.x, gpsi->ptCursor.y, FALSE);
 +    }
 +    else
 +    {
 +        CurInfo->CursorClipInfo.IsClipped = FALSE;
 +    }
 +
 +    return TRUE;
 +}
 +
 +/*
 + * @implemented
 + */
 +BOOL
 +APIENTRY
 +NtUserClipCursor(
 +    RECTL *prcl)
 +{
 +    /* FIXME - check if process has WINSTA_WRITEATTRIBUTES */
 +    RECTL rclLocal;
 +    BOOL bResult;
 +
 +    if (prcl)
 +    {
 +        _SEH2_TRY
 +        {
 +            /* Probe and copy rect */
 +            ProbeForRead(prcl, sizeof(RECTL), 1);
 +            rclLocal = *prcl;
 +        }
 +        _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
 +        {
 +            SetLastWin32Error(ERROR_INVALID_PARAMETER);
 +            _SEH2_YIELD(return FALSE;)
 +        }
 +        _SEH2_END
 +
 +        prcl = &rclLocal;
 +    }
 +
 +    UserEnterExclusive();
 +
 +    /* Call the internal function */
 +    bResult = UserClipCursor(prcl);
 +
 +    UserLeave();
 +
 +    return bResult;
 +}
 +
 +
 +/*
 + * @implemented
 + */
 +BOOL
 +APIENTRY
 +NtUserDestroyCursor(
 +    HANDLE hCurIcon,
 +    DWORD Unknown)
 +{
 +    PCURICON_OBJECT CurIcon;
 +    BOOL ret;
 +    DECLARE_RETURN(BOOL);
 +
 +    DPRINT("Enter NtUserDestroyCursorIcon\n");
 +    UserEnterExclusive();
 +
 +    if (!(CurIcon = UserGetCurIconObject(hCurIcon)))
 +    {
 +        RETURN(FALSE);
 +    }
 +
 +    ret = IntDestroyCurIconObject(CurIcon, FALSE);
 +    /* Note: IntDestroyCurIconObject will remove our reference for us! */
 +
 +    RETURN(ret);
 +
 +CLEANUP:
 +    DPRINT("Leave NtUserDestroyCursorIcon, ret=%i\n",_ret_);
 +    UserLeave();
 +    END_CLEANUP;
 +}
 +
 +
 +/*
 + * @implemented
 + */
 +HICON
 +APIENTRY
 +NtUserFindExistingCursorIcon(
 +    HMODULE hModule,
 +    HRSRC hRsrc,
 +    LONG cx,
 +    LONG cy)
 +{
 +    PCURICON_OBJECT CurIcon;
 +    HANDLE Ret = (HANDLE)0;
 +    DECLARE_RETURN(HICON);
 +
 +    DPRINT("Enter NtUserFindExistingCursorIcon\n");
 +    UserEnterExclusive();
 +
 +    CurIcon = IntFindExistingCurIconObject(hModule, hRsrc, cx, cy);
 +    if (CurIcon)
 +    {
 +        Ret = CurIcon->Self;
 +
 +//      IntReleaseCurIconObject(CurIcon);//faxme: is this correct? does IntFindExistingCurIconObject add a ref?
 +        RETURN(Ret);
 +    }
 +
 +    SetLastWin32Error(ERROR_INVALID_CURSOR_HANDLE);
 +    RETURN((HANDLE)0);
 +
 +CLEANUP:
 +    DPRINT("Leave NtUserFindExistingCursorIcon, ret=%i\n",_ret_);
 +    UserLeave();
 +    END_CLEANUP;
 +}
 +
 +
 +/*
 + * @implemented
 + */
 +BOOL
 +APIENTRY
 +NtUserGetClipCursor(
 +    RECTL *lpRect)
 +{
 +    /* FIXME - check if process has WINSTA_READATTRIBUTES */
 +    PSYSTEM_CURSORINFO CurInfo;
 +    RECTL Rect;
 +    NTSTATUS Status;
 +    DECLARE_RETURN(BOOL);
 +
 +    DPRINT("Enter NtUserGetClipCursor\n");
 +    UserEnterExclusive();
 +
 +    if (!lpRect)
 +        RETURN(FALSE);
 +
 +    CurInfo = IntGetSysCursorInfo();
 +    if (CurInfo->CursorClipInfo.IsClipped)
 +    {
 +        Rect.left = CurInfo->CursorClipInfo.Left;
 +        Rect.top = CurInfo->CursorClipInfo.Top;
 +        Rect.right = CurInfo->CursorClipInfo.Right;
 +        Rect.bottom = CurInfo->CursorClipInfo.Bottom;
 +    }
 +    else
 +    {
 +        Rect.left = 0;
 +        Rect.top = 0;
 +        Rect.right = UserGetSystemMetrics(SM_CXSCREEN);
 +        Rect.bottom = UserGetSystemMetrics(SM_CYSCREEN);
 +    }
 +
 +    Status = MmCopyToCaller(lpRect, &Rect, sizeof(RECT));
 +    if (!NT_SUCCESS(Status))
 +    {
 +        SetLastNtError(Status);
 +        RETURN(FALSE);
 +    }
 +
 +    RETURN(TRUE);
 +
 +CLEANUP:
 +    DPRINT("Leave NtUserGetClipCursor, ret=%i\n",_ret_);
 +    UserLeave();
 +    END_CLEANUP;
 +}
 +
 +
 +/*
 + * @implemented
 + */
 +HCURSOR
 +APIENTRY
 +NtUserSetCursor(
 +    HCURSOR hCursor)
 +{
 +    PCURICON_OBJECT CurIcon;
 +    HICON OldCursor;
 +    DECLARE_RETURN(HCURSOR);
 +
 +    DPRINT("Enter NtUserSetCursor\n");
 +    UserEnterExclusive();
 +
 +    if (hCursor)
 +    {
 +        if (!(CurIcon = UserGetCurIconObject(hCursor)))
 +        {
 +            RETURN(NULL);
 +        }
 +    }
 +    else
 +    {
 +        CurIcon = NULL;
 +    }
 +
 +    OldCursor = UserSetCursor(CurIcon, FALSE);
 +
 +    if (CurIcon)
 +    {
 +        UserDereferenceObject(CurIcon);
 +    }
 +
 +    RETURN(OldCursor);
 +
 +CLEANUP:
 +    DPRINT("Leave NtUserSetCursor, ret=%i\n",_ret_);
 +    UserLeave();
 +    END_CLEANUP;
 +}
 +
 +
 +/*
 + * @implemented
 + */
 +BOOL
 +APIENTRY
 +NtUserSetCursorContents(
 +    HANDLE hCurIcon,
 +    PICONINFO UnsafeIconInfo)
 +{
 +    PCURICON_OBJECT CurIcon;
 +    ICONINFO IconInfo;
 +    PSURFACE psurfBmp;
 +    NTSTATUS Status;
 +    BOOL Ret = FALSE;
 +    DECLARE_RETURN(BOOL);
 +
 +    DPRINT("Enter NtUserSetCursorContents\n");
 +    UserEnterExclusive();
 +
 +    if (!(CurIcon = UserGetCurIconObject(hCurIcon)))
 +    {
 +        RETURN(FALSE);
 +    }
 +
 +    /* Copy fields */
 +    Status = MmCopyFromCaller(&IconInfo, UnsafeIconInfo, sizeof(ICONINFO));
 +    if (!NT_SUCCESS(Status))
 +    {
 +        SetLastNtError(Status);
 +        goto done;
 +    }
 +
 +    /* Delete old bitmaps */
 +    if ((CurIcon->IconInfo.hbmColor)
 +                      && (CurIcon->IconInfo.hbmColor != IconInfo.hbmColor))
 +    {
 +        GreDeleteObject(CurIcon->IconInfo.hbmColor);
 +    }
 +    if ((CurIcon->IconInfo.hbmMask)
 +                      && CurIcon->IconInfo.hbmMask != IconInfo.hbmMask)
 +    {
 +        GreDeleteObject(CurIcon->IconInfo.hbmMask);
 +    }
 +
 +    /* Copy new IconInfo field */
 +    CurIcon->IconInfo = IconInfo;
 +
 +    psurfBmp = SURFACE_LockSurface(CurIcon->IconInfo.hbmColor);
 +    if (psurfBmp)
 +    {
 +        CurIcon->Size.cx = psurfBmp->SurfObj.sizlBitmap.cx;
 +        CurIcon->Size.cy = psurfBmp->SurfObj.sizlBitmap.cy;
 +        SURFACE_UnlockSurface(psurfBmp);
 +        GDIOBJ_SetOwnership(CurIcon->IconInfo.hbmColor, NULL);
 +    }
 +    else
 +    {
 +        psurfBmp = SURFACE_LockSurface(CurIcon->IconInfo.hbmMask);
 +        if (!psurfBmp)
 +            goto done;
 +
 +        CurIcon->Size.cx = psurfBmp->SurfObj.sizlBitmap.cx;
 +        CurIcon->Size.cy = psurfBmp->SurfObj.sizlBitmap.cy / 2;
 +
 +        SURFACE_UnlockSurface(psurfBmp);
 +        GDIOBJ_SetOwnership(CurIcon->IconInfo.hbmMask, NULL);
 +    }
 +
 +    Ret = TRUE;
 +
 +done:
 +
 +    if (CurIcon)
 +    {
 +        UserDereferenceObject(CurIcon);
 +    }
 +    RETURN(Ret);
 +
 +CLEANUP:
 +    DPRINT("Leave NtUserSetCursorContents, ret=%i\n",_ret_);
 +    UserLeave();
 +    END_CLEANUP;
 +}
 +
 +
 +/*
 + * @implemented
 + */
 +#if 0
 +BOOL
 +APIENTRY
 +NtUserSetCursorIconData(
 +    HANDLE Handle,
 +    HMODULE hModule,
 +    PUNICODE_STRING pstrResName,
 +    PICONINFO pIconInfo)
 +{
 +    PCURICON_OBJECT CurIcon;
 +    PSURFACE psurfBmp;
 +    NTSTATUS Status = STATUS_SUCCESS;
 +    BOOL Ret = FALSE;
 +    DECLARE_RETURN(BOOL);
 +
 +    DPRINT("Enter NtUserSetCursorIconData\n");
 +    UserEnterExclusive();
 +
 +    if (!(CurIcon = UserGetCurIconObject(Handle)))
 +    {
 +        RETURN(FALSE);
 +    }
 +
 +    CurIcon->hModule = hModule;
 +    CurIcon->hRsrc = NULL; //hRsrc;
 +    CurIcon->hGroupRsrc = NULL; //hGroupRsrc;
 +
 +    _SEH2_TRY
 +    {
 +        ProbeForRead(pIconInfo, sizeof(ICONINFO), 1);
 +        RtlCopyMemory(&CurIcon->IconInfo, pIconInfo, sizeof(ICONINFO));
 +
 +        CurIcon->IconInfo.hbmMask = BITMAP_CopyBitmap(pIconInfo->hbmMask);
 +        CurIcon->IconInfo.hbmColor = BITMAP_CopyBitmap(pIconInfo->hbmColor);
 +
 +        if (CurIcon->IconInfo.hbmColor)
 +        {
 +            if ((psurfBmp = SURFACE_LockSurface(CurIcon->IconInfo.hbmColor)))
 +            {
 +                CurIcon->Size.cx = psurfBmp->SurfObj.sizlBitmap.cx;
 +                CurIcon->Size.cy = psurfBmp->SurfObj.sizlBitmap.cy;
 +                SURFACE_UnlockSurface(psurfBmp);
 +                GDIOBJ_SetOwnership(GdiHandleTable, CurIcon->IconInfo.hbmMask, NULL);
 +            }
 +        }
 +        if (CurIcon->IconInfo.hbmMask)
 +        {
 +            if (CurIcon->IconInfo.hbmColor == NULL)
 +            {
 +                if ((psurfBmp = SURFACE_LockSurface(CurIcon->IconInfo.hbmMask)))
 +                {
 +                    CurIcon->Size.cx = psurfBmp->SurfObj.sizlBitmap.cx;
 +                    CurIcon->Size.cy = psurfBmp->SurfObj.sizlBitmap.cy;
 +                    SURFACE_UnlockSurface(psurfBmp);
 +                }
 +            }
 +            GDIOBJ_SetOwnership(GdiHandleTable, CurIcon->IconInfo.hbmMask, NULL);
 +        }
 +    }
 +    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
 +    {
 +        Status = _SEH2_GetExceptionCode();
 +    }
 +    _SEH2_END
 +
 +    if (!NT_SUCCESS(Status))
 +        SetLastNtError(Status);
 +    else
 +        Ret = TRUE;
 +
 +    UserDereferenceObject(CurIcon);
 +    RETURN(Ret);
 +
 +CLEANUP:
 +    DPRINT("Leave NtUserSetCursorIconData, ret=%i\n",_ret_);
 +    UserLeave();
 +    END_CLEANUP;
 +}
 +#else
 +BOOL
 +APIENTRY
 +NtUserSetCursorIconData(
 +    HANDLE hCurIcon,
 +    PBOOL fIcon,
 +    POINT *Hotspot,
 +    HMODULE hModule,
 +    HRSRC hRsrc,
 +    HRSRC hGroupRsrc)
 +{
 +    PCURICON_OBJECT CurIcon;
 +    NTSTATUS Status;
 +    POINT SafeHotspot;
 +    BOOL Ret = FALSE;
 +    DECLARE_RETURN(BOOL);
 +
 +    DPRINT("Enter NtUserSetCursorIconData\n");
 +    UserEnterExclusive();
 +
 +    if (!(CurIcon = UserGetCurIconObject(hCurIcon)))
 +    {
 +        RETURN(FALSE);
 +    }
 +
 +    CurIcon->hModule = hModule;
 +    CurIcon->hRsrc = hRsrc;
 +    CurIcon->hGroupRsrc = hGroupRsrc;
 +
 +    /* Copy fields */
 +    if (fIcon)
 +    {
 +        Status = MmCopyFromCaller(&CurIcon->IconInfo.fIcon, fIcon, sizeof(BOOL));
 +        if (!NT_SUCCESS(Status))
 +        {
 +            SetLastNtError(Status);
 +            goto done;
 +        }
 +    }
 +    else
 +    {
 +        if (!Hotspot)
 +            Ret = TRUE;
 +    }
 +
 +    if (Hotspot)
 +    {
 +        Status = MmCopyFromCaller(&SafeHotspot, Hotspot, sizeof(POINT));
 +        if (NT_SUCCESS(Status))
 +        {
 +            CurIcon->IconInfo.xHotspot = SafeHotspot.x;
 +            CurIcon->IconInfo.yHotspot = SafeHotspot.y;
 +
 +            Ret = TRUE;
 +        }
 +        else
 +            SetLastNtError(Status);
 +    }
 +
 +    if (!fIcon && !Hotspot)
 +    {
 +        Ret = TRUE;
 +    }
 +
 +done:
 +      if(Ret)
 +      {
 +              /* This icon is shared now */
 +              GDIOBJ_SetOwnership(CurIcon->IconInfo.hbmMask, NULL);
 +              if(CurIcon->IconInfo.hbmColor)
 +              {
 +                      GDIOBJ_SetOwnership(CurIcon->IconInfo.hbmColor, NULL);
 +              }
 +      }
 +    UserDereferenceObject(CurIcon);
 +    RETURN(Ret);
 +
 +
 +CLEANUP:
 +    DPRINT("Leave NtUserSetCursorIconData, ret=%i\n",_ret_);
 +    UserLeave();
 +    END_CLEANUP;
 +}
 +#endif
 +
 +/*
 + * @unimplemented
 + */
 +BOOL
 +APIENTRY
 +NtUserSetSystemCursor(
 +    HCURSOR hcur,
 +    DWORD id)
 +{
 +    return FALSE;
 +}
 +
 +/* Mostly inspired from wine code */
 +BOOL
 +UserDrawIconEx(
 +    HDC hDc,
 +    INT xLeft,
 +    INT yTop,
 +    PCURICON_OBJECT pIcon,
 +    INT cxWidth,
 +    INT cyHeight,
 +    UINT istepIfAniCur,
 +    HBRUSH hbrFlickerFreeDraw,
 +    UINT diFlags)
 +{
-     INT iOldBkColor = 0, iOldTxtColor = 0;
-     HDC hMemDC, hDestDC = hDc;
-     HGDIOBJ hOldOffBrush = 0;
-     HGDIOBJ hOldOffBmp = 0;
-     HBITMAP hTmpBmp = 0, hOffBmp = 0;
-     BOOL bAlpha = FALSE;
-     INT x=xLeft, y=yTop;
-     hbmMask = pIcon->IconInfo.hbmMask;
-     hbmColor = pIcon->IconInfo.hbmColor;
++    PSURFACE psurfColor = NULL, psurfMask, psurfDst = NULL;
++    HGDIOBJ hObjs[3];
++    PGDIOBJ pObjs[3];
 +    BOOL DoFlickerFree;
-     if (!hbmMask || !IntGdiGetObject(hbmMask, sizeof(BITMAP), (PVOID)&bm))
++    PDC pdc;
++    HSURF hsurfDst = NULL;
++    RECTL rcSrc, rcDst;
++    CLIPOBJ clo, *pclo;
++    EXLATEOBJ exlo;
++    BOOL bAlpha = FALSE, Ret = FALSE, bStretch;
 +
 +    if (istepIfAniCur)
 +        DPRINT1("NtUserDrawIconEx: istepIfAniCur is not supported!\n");
 +
-     if (hbmColor && !IntGdiGetObject(hbmColor, sizeof(BITMAP), (PVOID)&bmpColor))
++    DPRINT("Flags : 0x%08x\n", diFlags);
++
++    hObjs[0] = pIcon->IconInfo.hbmMask;
++    hObjs[1] = pIcon->IconInfo.hbmColor;
++    hObjs[2] = hDc;
++    GDIOBJ_LockMultipleObjs(3, hObjs, pObjs);
++    psurfMask = pObjs[0];
++    psurfColor = pObjs[1];
++    pdc = pObjs[2];
++
++    if (!pIcon->IconInfo.hbmMask
++         || !psurfMask)
 +    {
++        DPRINT1("No hbmMask?!\n");
++        if(pdc) DC_UnlockDc(pdc);
++        if(psurfColor) SURFACE_UnlockSurface(psurfColor);
 +        return FALSE;
 +    }
 +
-     if(!(hMemDC = NtGdiCreateCompatibleDC(hDc)))
++    if (pIcon->IconInfo.hbmColor
++         && !psurfColor)
 +    {
++        DPRINT1("Unable to lock the color Bitmap?!\n");
++        SURFACE_UnlockSurface(psurfMask);
++        if(pdc) DC_UnlockDc(pdc);
 +        return FALSE;
 +    }
 +
-         DPRINT1("NtGdiCreateCompatibleDC failed!\n");
++    if(!psurfColor)
++    {
++        DPRINT("Monochrome Icon\n");
++        psurfColor = psurfMask;
++        RECTL_vSetRect(&rcSrc, 0, pIcon->Size.cy, pIcon->Size.cx, 2*pIcon->Size.cy);
++    }
++    else
 +    {
-     if (hbmColor
-             && (bmpColor.bmBitsPixel == 32)
++        DPRINT("Color Icon\n");
++        RECTL_vSetRect(&rcSrc, 0, 0, pIcon->Size.cx, pIcon->Size.cy);
++    }
++
++    if(!pdc)
++    {
++        SetLastWin32Error(ERROR_INVALID_PARAMETER);
++        SURFACE_UnlockSurface(psurfMask);
++        if(psurfColor != psurfMask) SURFACE_UnlockSurface(psurfColor);
++        DPRINT1("Invalid DC!\n");
 +        return FALSE;
 +    }
 +
 +    /* Check for alpha */
-         SURFACE *psurfOff = NULL;
++    if ((BitsPerFormat(psurfColor->SurfObj.iBitmapFormat) == 32)
 +            && (diFlags & DI_IMAGE))
 +    {
-         psurfOff = SURFACE_LockSurface(hbmColor);
-         if (psurfOff)
 +        PFN_DIB_GetPixel fnSource_GetPixel = NULL;
 +        INT i, j;
 +
 +        /* In order to correctly display 32 bit icons Windows first scans the image,
 +           because information about transparency is not stored in any image's headers */
-             fnSource_GetPixel = DibFunctionsForBitmapFormat[psurfOff->SurfObj.iBitmapFormat].DIB_GetPixel;
-             if (fnSource_GetPixel)
++        fnSource_GetPixel = DibFunctionsForBitmapFormat[psurfColor->SurfObj.iBitmapFormat].DIB_GetPixel;
++        if (fnSource_GetPixel)
 +        {
-                 for (i = 0; i < psurfOff->SurfObj.sizlBitmap.cx; i++)
++            for (i = 0; i < psurfColor->SurfObj.sizlBitmap.cx; i++)
 +            {
-                     for (j = 0; j < psurfOff->SurfObj.sizlBitmap.cy; j++)
-                     {
-                         bAlpha = ((BYTE)(fnSource_GetPixel(&psurfOff->SurfObj, i, j) >> 24) & 0xff);
-                         if (bAlpha)
-                             break;
-                     }
++                for (j = 0; j < psurfColor->SurfObj.sizlBitmap.cy; j++)
 +                {
-             SURFACE_UnlockSurface(psurfOff);
++                    bAlpha = ((BYTE)(fnSource_GetPixel(&psurfColor->SurfObj, i, j) >> 24) & 0xff);
 +                    if (bAlpha)
 +                        break;
 +                }
++                if (bAlpha)
++                    break;
 +            }
-         hDestDC = NtGdiCreateCompatibleDC(hDc);
-         if(!hDestDC)
 +        }
 +    }
 +
 +    if (!cxWidth)
 +        cxWidth = ((diFlags & DI_DEFAULTSIZE) ?
 +                   UserGetSystemMetrics(SM_CXICON) : pIcon->Size.cx);
 +
 +    if (!cyHeight)
 +        cyHeight = ((diFlags & DI_DEFAULTSIZE) ?
 +                    UserGetSystemMetrics(SM_CYICON) : pIcon->Size.cy);
 +
++    /* Check stretching */
++    bStretch = (pIcon->Size.cx != cxWidth) || (pIcon->Size.cy != cyHeight);
++
 +    DoFlickerFree = (hbrFlickerFreeDraw &&
 +                     (GDI_HANDLE_GET_TYPE(hbrFlickerFreeDraw) == GDI_OBJECT_TYPE_BRUSH));
 +
 +    if (DoFlickerFree)
 +    {
-             DPRINT1("NtGdiCreateCompatibleDC failed!\n");
-             Ret = FALSE;
-             goto Cleanup ;
++        EBRUSHOBJ ebo;
++        PBRUSH pBrush ;
++        POINTL ptBrushOrig;
++
++        pBrush = BRUSH_LockBrush(hbrFlickerFreeDraw);
++        if(!pBrush)
 +        {
-         hOffBmp = NtGdiCreateCompatibleBitmap(hDc, cxWidth, cyHeight);
-         if(!hOffBmp)
++            SetLastWin32Error(ERROR_INVALID_PARAMETER);
++            DPRINT1("Invalid brush!\n");
++            goto cleanup;
 +        }
-             DPRINT1("NtGdiCreateCompatibleBitmap failed!\n");
-             goto Cleanup ;
++
++        hsurfDst = IntCreateCompatibleBitmap(pdc, cxWidth, cyHeight);
++        if(!hsurfDst)
 +        {
-         hOldOffBmp = NtGdiSelectBitmap(hDestDC, hOffBmp);
-         hOldOffBrush = NtGdiSelectBrush(hDestDC, hbrFlickerFreeDraw);
-         NtGdiPatBlt(hDestDC, 0, 0, cxWidth, cyHeight, PATCOPY);
-         NtGdiSelectBrush(hDestDC, hOldOffBrush);
-         x=y=0;
++            DPRINT1("Error : Failed to allocate the offscreen surface\n");
++            goto cleanup;
 +        }
-     /* Set Background/foreground colors */
-     iOldTxtColor = IntGdiSetTextColor(hDc, 0); //black
-     iOldBkColor = IntGdiSetBkColor(hDc, 0x00FFFFFF); //white
++        psurfDst = SURFACE_LockSurface(hsurfDst);
++        if(!psurfDst)
++        {
++            DPRINT1("Error : Failed to lock the offScreen bitmap\n");
++            goto cleanup;
++        }
++        RECTL_vSetRect(&rcDst, 0, 0, cxWidth, cyHeight);
++
++        ptBrushOrig.x = pBrush->ptOrigin.x;
++        ptBrushOrig.y = pBrush->ptOrigin.y;
++
++        EBRUSHOBJ_vInit(&ebo, pBrush, pdc);
++
++        clo.iDComplexity =  DC_TRIVIAL;
++        pclo = &clo;
++
++        IntEngBitBlt(&psurfDst->SurfObj, NULL, NULL, pclo, NULL, &rcDst, NULL,
++                     NULL, &ebo.BrushObject, &ptBrushOrig, ROP3_TO_ROP4(PATCOPY));
++
++        EBRUSHOBJ_vCleanup(&ebo);
++        BRUSH_UnlockBrush(pBrush);
 +    }
++    else
++    {
++        RECT rcBmp;
++        RECTL_vSetRect(&rcDst, xLeft, yTop, xLeft + cxWidth, yTop + cyHeight);
++        IntLPtoDP(pdc, (LPPOINT)&rcDst, 2);
++        RECTL_vOffsetRect(&rcDst, pdc->ptlDCOrig.x, pdc->ptlDCOrig.y);
++
++        DC_vPrepareDCsForBlit(pdc, rcDst, NULL, rcDst );
 +
-         PSURFACE psurf;
++        if (pdc->pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY))
++            DC_vUpdateFillBrush(pdc);
++
++        psurfDst = pdc->dclevel.pSurface;
++        pclo = pdc->rosdc.CombinedClip;
++        RECTL_vSetRect(&rcBmp, 0, 0, psurfDst->SurfObj.sizlBitmap.cx, psurfDst->SurfObj.sizlBitmap.cy);
++        if(!RECTL_bIntersectRect(&rcDst, &rcDst, &rcBmp))
++        {
++            Ret = FALSE;
++            goto done;
++        }
++    }
++
++    /* Optimization : use directly the palette of the DC,
++     * so we XLATE only once, and then we directly copy bits */
++    EXLATEOBJ_vInitialize(&exlo, psurfColor->ppal, pdc->dclevel.pSurface->ppal, 0, 0, 0xFFFFFFFF);
 +
 +      if(bAlpha && (diFlags & DI_IMAGE))
 +      {
 +              BLENDFUNCTION pixelblend = { AC_SRC_OVER, 0, 255, AC_SRC_ALPHA };
 +        BYTE Alpha;
 +        INT i, j;
-         hMemBmp = BITMAP_CopyBitmap(hbmColor);
++        PSURFACE psurf = NULL;
 +        PBYTE ptr ;
 +        HBITMAP hMemBmp = NULL;
 +
-         SURFACE_UnlockSurface(psurf);
-         hTmpBmp = NtGdiSelectBitmap(hMemDC, hMemBmp);
-         Ret = NtGdiAlphaBlend(hDestDC,
-                                                 x,
-                                                     y,
-                               cxWidth,
-                               cyHeight,
-                               hMemDC,
-                               0,
-                               0,
-                               pIcon->Size.cx,
-                               pIcon->Size.cy,
-                               pixelblend,
-                               NULL);
-         NtGdiSelectBitmap(hMemDC, hTmpBmp);
++        hMemBmp = BITMAP_CopyBitmap(pIcon->IconInfo.hbmColor);
 +        if(!hMemBmp)
 +        {
 +            DPRINT1("BITMAP_CopyBitmap failed!");
 +            goto CleanupAlpha;
 +        }
 +
 +        psurf = SURFACE_LockSurface(hMemBmp);
 +        if(!psurf)
 +        {
 +            DPRINT1("SURFACE_LockSurface failed!\n");
 +            goto CleanupAlpha;
 +        }
 +
 +        /* premultiply with the alpha channel value */
 +        for (i = 0; i < psurf->SurfObj.sizlBitmap.cy; i++)
 +        {
 +                      ptr = (PBYTE)psurf->SurfObj.pvScan0 + i*psurf->SurfObj.lDelta;
 +            for (j = 0; j < psurf->SurfObj.sizlBitmap.cx; j++)
 +            {
 +                Alpha = ptr[3];
 +                ptr[0] = (ptr[0] * Alpha) / 0xff;
 +                ptr[1] = (ptr[1] * Alpha) / 0xff;
 +                ptr[2] = (ptr[2] * Alpha) / 0xff;
 +
 +                              ptr += 4;
 +            }
 +        }
 +
-     if (diFlags & DI_MASK)
++        DPRINT("Performing alpha blending\n");
++        Ret = IntEngAlphaBlend(&psurfDst->SurfObj,
++                               &psurf->SurfObj,
++                               pclo,
++                               &exlo.xlo,
++                               &rcDst,
++                               &rcSrc,
++                               (BLENDOBJ*)&pixelblend);
++
 +    CleanupAlpha:
++        if(psurf) SURFACE_UnlockSurface(psurf);
 +        if(hMemBmp) NtGdiDeleteObjectApp(hMemBmp);
 +              if(Ret) goto done;
++        else DPRINT1("IntEngAlphaBlend failed!\n");
 +    }
 +
-         hTmpBmp = NtGdiSelectBitmap(hMemDC, hbmMask);
-         NtGdiStretchBlt(hDestDC,
-                         x,
-                         y,
-                         cxWidth,
-                         cyHeight,
-                         hMemDC,
-                         0,
-                         0,
-                         pIcon->Size.cx,
-                         pIcon->Size.cy,
-                         SRCAND,
-                         0);
-         NtGdiSelectBitmap(hMemDC, hTmpBmp);
-     }
-     if(diFlags & DI_IMAGE)
-     {
-               if (hbmColor)
++    if (diFlags & DI_IMAGE)
 +    {
-             DWORD rop = (diFlags & DI_MASK) ? SRCINVERT : SRCCOPY ;
-             hTmpBmp = NtGdiSelectBitmap(hMemDC, hbmColor);
-             NtGdiStretchBlt(hDestDC,
-                             x,
-                             y,
-                             cxWidth,
-                             cyHeight,
-                             hMemDC,
-                             0,
-                             0,
-                             pIcon->Size.cx,
-                             pIcon->Size.cy,
-                             rop,
-                             0);
-             NtGdiSelectBitmap(hMemDC, hTmpBmp);
++        POINTL ptMaskOrig = {0,0};
++        if(bStretch)
 +        {
-             /* Mask bitmap holds the information in its second half */
-             DWORD rop = (diFlags & DI_MASK) ? SRCINVERT : SRCCOPY ;
-             hTmpBmp = NtGdiSelectBitmap(hMemDC, hbmMask);
-             NtGdiStretchBlt(hDestDC,
-                             x,
-                             y,
-                             cxWidth,
-                             cyHeight,
-                             hMemDC,
-                             0,
-                             pIcon->Size.cy,
-                             pIcon->Size.cx,
-                             pIcon->Size.cy,
-                             rop,
-                             0);
-             NtGdiSelectBitmap(hMemDC, hTmpBmp);
++            DPRINT("Stretching\n");
++            Ret = IntEngStretchBlt(&psurfDst->SurfObj,
++                                   &psurfColor->SurfObj,
++                                   (diFlags & DI_MASK) ? &psurfMask->SurfObj : NULL,
++                                   pclo,
++                                   &exlo.xlo,
++                                   &rcDst,
++                                   &rcSrc,
++                                   (diFlags & DI_MASK) ? &ptMaskOrig : NULL,
++                                   NULL,
++                                   NULL,
++                                   (diFlags & DI_MASK) ? R4_MASK : ROP3_TO_ROP4(SRCCOPY));
++            if(!Ret) DPRINT1("IntEngStretchBlt Failed\n");
 +        }
 +        else
 +        {
-     if(hDestDC != hDc)
++            DPRINT("Blting\n");
++            Ret = IntEngBitBlt(&psurfDst->SurfObj,
++                               &psurfColor->SurfObj,
++                               (diFlags & DI_MASK) ? &psurfMask->SurfObj : NULL,
++                               pclo,
++                               &exlo.xlo,
++                               &rcDst,
++                               (PPOINTL)&rcSrc,
++                               (diFlags & DI_MASK) ? &ptMaskOrig : NULL,
++                               NULL,
++                               NULL,
++                               (diFlags & DI_MASK) ? R4_MASK : ROP3_TO_ROP4(SRCCOPY));
++            if(!Ret) DPRINT1("IntEngBitBlt Failed\n");
 +        }
 +    }
++    else
++    {
++        DPRINT1("Uh? Calling DrawIcon without anything to draw? diFlags %d\n", diFlags);
++    }
 +
 +done:
-         NtGdiBitBlt(hDc, xLeft, yTop, cxWidth, cyHeight, hDestDC, 0, 0, SRCCOPY, 0, 0);
-     }
++    if(DoFlickerFree && Ret)
 +    {
-     /* Restore foreground and background colors */
-     IntGdiSetBkColor(hDc, iOldBkColor);
-     IntGdiSetTextColor(hDc, iOldTxtColor);
++        POINTL ptSrc = {0,0};
++        RECTL rcBmp;
++
++        RECTL_vSetRect(&rcDst, xLeft, yTop, xLeft + cxWidth, yTop + cyHeight);
++
++        IntLPtoDP(pdc, (LPPOINT)&rcDst, 2);
++
++        RECTL_vOffsetRect(&rcDst, pdc->ptlDCOrig.x, pdc->ptlDCOrig.y);
++        DC_vPrepareDCsForBlit(pdc, rcDst, NULL, rcDst );
++
++        if (pdc->pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY))
++            DC_vUpdateFillBrush(pdc);
++
++        RECTL_vSetRect(&rcBmp, 0, 0,
++                       pdc->dclevel.pSurface->SurfObj.sizlBitmap.cx,
++                       pdc->dclevel.pSurface->SurfObj.sizlBitmap.cy);
 +
-     Ret = TRUE ;
++        if(RECTL_bIntersectRect(&rcDst, &rcDst, &rcBmp))
++        {
++            /* Copy everything */
++            DPRINT("Copying bits from offscreen buffer\n");
++            Ret = IntEngCopyBits(&pdc->dclevel.pSurface->SurfObj,
++                                 &psurfDst->SurfObj,
++                                 pdc->rosdc.CombinedClip,
++                                 gpxloTrivial,
++                                 &rcDst,
++                                 &ptSrc);
++            if(!Ret) DPRINT1("IntEngCopyBits Failed\n");
++        }
++
++        DC_vFinishBlit(pdc, NULL);
++    }
 +
- Cleanup:
-     NtGdiDeleteObjectApp(hMemDC);
-     if(hDestDC != hDc)
++    if(!DoFlickerFree) DC_vFinishBlit(pdc, NULL);
++    EXLATEOBJ_vCleanup(&exlo);
 +
-         if(hOldOffBmp) NtGdiSelectBitmap(hDestDC, hOldOffBmp);
-         NtGdiDeleteObjectApp(hDestDC);
-         if(hOffBmp) NtGdiDeleteObjectApp(hOffBmp);
++cleanup:
++    if(psurfColor != psurfMask)
++        SURFACE_UnlockSurface(psurfColor);
++    SURFACE_UnlockSurface(psurfMask);
++    if(hsurfDst)
 +    {
-     return Ret;
++        if(psurfDst) SURFACE_UnlockSurface(psurfDst);
++        GreDeleteObject(hsurfDst);
 +    }
++    DC_UnlockDc(pdc);
 +
++    DPRINT("return %s\n", Ret ? "TRUE" : "FALSE") ;
++
++    return Ret ;
 +}
 +
 +/*
 + * @implemented
 + */
 +BOOL
 +APIENTRY
 +NtUserDrawIconEx(
 +    HDC hdc,
 +    int xLeft,
 +    int yTop,
 +    HICON hIcon,
 +    int cxWidth,
 +    int cyHeight,
 +    UINT istepIfAniCur,
 +    HBRUSH hbrFlickerFreeDraw,
 +    UINT diFlags,
 +    BOOL bMetaHDC, // When TRUE, GDI functions need to be handled in User32!
 +    PVOID pDIXData)
 +{
 +    PCURICON_OBJECT pIcon;
 +    BOOL Ret;
 +
 +    DPRINT("Enter NtUserDrawIconEx\n");
 +    UserEnterExclusive();
 +
 +    if (!(pIcon = UserGetCurIconObject(hIcon)))
 +    {
 +        DPRINT1("UserGetCurIconObject() failed!\n");
 +        UserLeave();
 +        return FALSE;
 +    }
 +
 +    Ret = UserDrawIconEx(hdc,
 +                         xLeft,
 +                         yTop,
 +                         pIcon,
 +                         cxWidth,
 +                         cyHeight,
 +                         istepIfAniCur,
 +                         hbrFlickerFreeDraw,
 +                         diFlags);
 +
 +    UserDereferenceObject(pIcon);
 +
 +    UserLeave();
 +    return Ret;
 +}
 +
index 5b59a59,0000000..052901c
mode 100644,000000..100644
--- /dev/null
@@@ -1,1148 -1,0 +1,1116 @@@
-     HBITMAP hOldMaskBitmap, hBitmap2, hOldBitmap2, hBitmap3, hOldBitmap3;
-     HDC hDCMask, hDC1, hDC2;
-     static const DWORD ROP3Table[256] =
-     {
-         0x00000042, 0x00010289,
-         0x00020C89, 0x000300AA,
-         0x00040C88, 0x000500A9,
-         0x00060865, 0x000702C5,
-         0x00080F08, 0x00090245,
-         0x000A0329, 0x000B0B2A,
-         0x000C0324, 0x000D0B25,
-         0x000E08A5, 0x000F0001,
-         0x00100C85, 0x001100A6,
-         0x00120868, 0x001302C8,
-         0x00140869, 0x001502C9,
-         0x00165CCA, 0x00171D54,
-         0x00180D59, 0x00191CC8,
-         0x001A06C5, 0x001B0768,
-         0x001C06CA, 0x001D0766,
-         0x001E01A5, 0x001F0385,
-         0x00200F09, 0x00210248,
-         0x00220326, 0x00230B24,
-         0x00240D55, 0x00251CC5,
-         0x002606C8, 0x00271868,
-         0x00280369, 0x002916CA,
-         0x002A0CC9, 0x002B1D58,
-         0x002C0784, 0x002D060A,
-         0x002E064A, 0x002F0E2A,
-         0x0030032A, 0x00310B28,
-         0x00320688, 0x00330008,
-         0x003406C4, 0x00351864,
-         0x003601A8, 0x00370388,
-         0x0038078A, 0x00390604,
-         0x003A0644, 0x003B0E24,
-         0x003C004A, 0x003D18A4,
-         0x003E1B24, 0x003F00EA,
-         0x00400F0A, 0x00410249,
-         0x00420D5D, 0x00431CC4,
-         0x00440328, 0x00450B29,
-         0x004606C6, 0x0047076A,
-         0x00480368, 0x004916C5,
-         0x004A0789, 0x004B0605,
-         0x004C0CC8, 0x004D1954,
-         0x004E0645, 0x004F0E25,
-         0x00500325, 0x00510B26,
-         0x005206C9, 0x00530764,
-         0x005408A9, 0x00550009,
-         0x005601A9, 0x00570389,
-         0x00580785, 0x00590609,
-         0x005A0049, 0x005B18A9,
-         0x005C0649, 0x005D0E29,
-         0x005E1B29, 0x005F00E9,
-         0x00600365, 0x006116C6,
-         0x00620786, 0x00630608,
-         0x00640788, 0x00650606,
-         0x00660046, 0x006718A8,
-         0x006858A6, 0x00690145,
-         0x006A01E9, 0x006B178A,
-         0x006C01E8, 0x006D1785,
-         0x006E1E28, 0x006F0C65,
-         0x00700CC5, 0x00711D5C,
-         0x00720648, 0x00730E28,
-         0x00740646, 0x00750E26,
-         0x00761B28, 0x007700E6,
-         0x007801E5, 0x00791786,
-         0x007A1E29, 0x007B0C68,
-         0x007C1E24, 0x007D0C69,
-         0x007E0955, 0x007F03C9,
-         0x008003E9, 0x00810975,
-         0x00820C49, 0x00831E04,
-         0x00840C48, 0x00851E05,
-         0x008617A6, 0x008701C5,
-         0x008800C6, 0x00891B08,
-         0x008A0E06, 0x008B0666,
-         0x008C0E08, 0x008D0668,
-         0x008E1D7C, 0x008F0CE5,
-         0x00900C45, 0x00911E08,
-         0x009217A9, 0x009301C4,
-         0x009417AA, 0x009501C9,
-         0x00960169, 0x0097588A,
-         0x00981888, 0x00990066,
-         0x009A0709, 0x009B07A8,
-         0x009C0704, 0x009D07A6,
-         0x009E16E6, 0x009F0345,
-         0x00A000C9, 0x00A11B05,
-         0x00A20E09, 0x00A30669,
-         0x00A41885, 0x00A50065,
-         0x00A60706, 0x00A707A5,
-         0x00A803A9, 0x00A90189,
-         0x00AA0029, 0x00AB0889,
-         0x00AC0744, 0x00AD06E9,
-         0x00AE0B06, 0x00AF0229,
-         0x00B00E05, 0x00B10665,
-         0x00B21974, 0x00B30CE8,
-         0x00B4070A, 0x00B507A9,
-         0x00B616E9, 0x00B70348,
-         0x00B8074A, 0x00B906E6,
-         0x00BA0B09, 0x00BB0226,
-         0x00BC1CE4, 0x00BD0D7D,
-         0x00BE0269, 0x00BF08C9,
-         0x00C000CA, 0x00C11B04,
-         0x00C21884, 0x00C3006A,
-         0x00C40E04, 0x00C50664,
-         0x00C60708, 0x00C707AA,
-         0x00C803A8, 0x00C90184,
-         0x00CA0749, 0x00CB06E4,
-         0x00CC0020, 0x00CD0888,
-         0x00CE0B08, 0x00CF0224,
-         0x00D00E0A, 0x00D1066A,
-         0x00D20705, 0x00D307A4,
-         0x00D41D78, 0x00D50CE9,
-         0x00D616EA, 0x00D70349,
-         0x00D80745, 0x00D906E8,
-         0x00DA1CE9, 0x00DB0D75,
-         0x00DC0B04, 0x00DD0228,
-         0x00DE0268, 0x00DF08C8,
-         0x00E003A5, 0x00E10185,
-         0x00E20746, 0x00E306EA,
-         0x00E40748, 0x00E506E5,
-         0x00E61CE8, 0x00E70D79,
-         0x00E81D74, 0x00E95CE6,
-         0x00EA02E9, 0x00EB0849,
-         0x00EC02E8, 0x00ED0848,
-         0x00EE0086, 0x00EF0A08,
-         0x00F00021, 0x00F10885,
-         0x00F20B05, 0x00F3022A,
-         0x00F40B0A, 0x00F50225,
-         0x00F60265, 0x00F708C5,
-         0x00F802E5, 0x00F90845,
-         0x00FA0089, 0x00FB0A09,
-         0x00FC008A, 0x00FD0A0A,
-         0x00FE02A9, 0x00FF0062,
-     };
 +/*
 +*  ReactOS W32 Subsystem
 +*  Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
 +*
 +*  This program is free software; you can redistribute it and/or modify
 +*  it under the terms of the GNU General Public License as published by
 +*  the Free Software Foundation; either version 2 of the License, or
 +*  (at your option) any later version.
 +*
 +*  This program is distributed in the hope that it will be useful,
 +*  but WITHOUT ANY WARRANTY; without even the implied warranty of
 +*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 +*  GNU General Public License for more details.
 +*
 +*  You should have received a copy of the GNU General Public License along
 +*  with this program; if not, write to the Free Software Foundation, Inc.,
 +*  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 +*/
 +/* $Id: bitmaps.c 28300 2007-08-12 15:20:09Z tkreuzer $ */
 +
 +#include <win32k.h>
 +
 +#define NDEBUG
 +#include <debug.h>
 +
 +
 +
 +BOOL APIENTRY
 +NtGdiAlphaBlend(
 +    HDC hDCDest,
 +    LONG XOriginDest,
 +    LONG YOriginDest,
 +    LONG WidthDest,
 +    LONG HeightDest,
 +    HDC hDCSrc,
 +    LONG XOriginSrc,
 +    LONG YOriginSrc,
 +    LONG WidthSrc,
 +    LONG HeightSrc,
 +    BLENDFUNCTION BlendFunc,
 +    HANDLE hcmXform)
 +{
 +    PDC DCDest;
 +    PDC DCSrc;
 +    HDC ahDC[2];
 +    PGDIOBJ apObj[2];
 +    SURFACE *BitmapDest, *BitmapSrc;
 +    RECTL DestRect, SourceRect;
 +    BOOL bResult;
 +    EXLATEOBJ exlo;
 +    BLENDOBJ BlendObj;
 +    BlendObj.BlendFunction = BlendFunc;
 +
 +    if (WidthDest < 0 || HeightDest < 0 || WidthSrc < 0 || HeightSrc < 0)
 +    {
 +        SetLastWin32Error(ERROR_INVALID_PARAMETER);
 +        return FALSE;
 +    }
 +
 +    DPRINT("Locking DCs\n");
 +    ahDC[0] = hDCDest;
 +    ahDC[1] = hDCSrc ;
 +    GDIOBJ_LockMultipleObjs(2, ahDC, apObj);
 +    DCDest = apObj[0];
 +    DCSrc = apObj[1];
 +
 +    if ((NULL == DCDest) || (NULL == DCSrc))
 +    {
 +        DPRINT1("Invalid dc handle (dest=0x%08x, src=0x%08x) passed to NtGdiAlphaBlend\n", hDCDest, hDCSrc);
 +        SetLastWin32Error(ERROR_INVALID_HANDLE);
 +        if(DCSrc) GDIOBJ_UnlockObjByPtr(&DCSrc->BaseObject);
 +        if(DCDest) GDIOBJ_UnlockObjByPtr(&DCDest->BaseObject);
 +        return FALSE;
 +    }
 +
 +    if (DCDest->dctype == DC_TYPE_INFO || DCDest->dctype == DCTYPE_INFO)
 +    {
 +        GDIOBJ_UnlockObjByPtr(&DCSrc->BaseObject);
 +        GDIOBJ_UnlockObjByPtr(&DCDest->BaseObject);
 +        /* Yes, Windows really returns TRUE in this case */
 +        return TRUE;
 +    }
 +
 +    DestRect.left   = XOriginDest;
 +    DestRect.top    = YOriginDest;
 +    DestRect.right  = XOriginDest + WidthDest;
 +    DestRect.bottom = YOriginDest + HeightDest;
 +    IntLPtoDP(DCDest, (LPPOINT)&DestRect, 2);
 +
 +    DestRect.left   += DCDest->ptlDCOrig.x;
 +    DestRect.top    += DCDest->ptlDCOrig.y;
 +    DestRect.right  += DCDest->ptlDCOrig.x;
 +    DestRect.bottom += DCDest->ptlDCOrig.y;
 +
 +    SourceRect.left   = XOriginSrc;
 +    SourceRect.top    = YOriginSrc;
 +    SourceRect.right  = XOriginSrc + WidthSrc;
 +    SourceRect.bottom = YOriginSrc + HeightSrc;
 +    IntLPtoDP(DCSrc, (LPPOINT)&SourceRect, 2);
 +
 +    SourceRect.left   += DCSrc->ptlDCOrig.x;
 +    SourceRect.top    += DCSrc->ptlDCOrig.y;
 +    SourceRect.right  += DCSrc->ptlDCOrig.x;
 +    SourceRect.bottom += DCSrc->ptlDCOrig.y;
 +
 +    if (!DestRect.right ||
 +        !DestRect.bottom ||
 +        !SourceRect.right ||
 +        !SourceRect.bottom)
 +    {
 +        GDIOBJ_UnlockObjByPtr(&DCSrc->BaseObject);
 +        GDIOBJ_UnlockObjByPtr(&DCDest->BaseObject);
 +        return TRUE;
 +    }
 +
 +    /* Prepare DCs for blit */
 +    DPRINT("Preparing DCs for blit\n");
 +    DC_vPrepareDCsForBlit(DCDest, DestRect, DCSrc, SourceRect);
 +
 +    /* Determine surfaces to be used in the bitblt */
 +    BitmapDest = DCDest->dclevel.pSurface;
 +    if (!BitmapDest)
 +    {
 +        bResult = FALSE ;
 +        goto leave ;
 +    }
 +
 +    BitmapSrc = DCSrc->dclevel.pSurface;
 +    if (!BitmapSrc)
 +    {
 +        bResult = FALSE;
 +        goto leave;
 +    }
 +
 +    /* Create the XLATEOBJ. */
 +    EXLATEOBJ_vInitXlateFromDCs(&exlo, DCSrc, DCDest);
 +
 +    /* Perform the alpha blend operation */
 +    DPRINT("Performing the alpha Blend\n");
 +    bResult = IntEngAlphaBlend(&BitmapDest->SurfObj,
 +                               &BitmapSrc->SurfObj,
 +                               DCDest->rosdc.CombinedClip,
 +                               &exlo.xlo,
 +                               &DestRect,
 +                               &SourceRect,
 +                               &BlendObj);
 +
 +    EXLATEOBJ_vCleanup(&exlo);
 +leave :
 +    DPRINT("Finishing blit\n");
 +    DC_vFinishBlit(DCDest, DCSrc);
 +    GDIOBJ_UnlockObjByPtr(&DCSrc->BaseObject);
 +    GDIOBJ_UnlockObjByPtr(&DCDest->BaseObject);
 +
 +    return bResult;
 +}
 +
 +BOOL APIENTRY
 +NtGdiBitBlt(
 +    HDC hDCDest,
 +    INT XDest,
 +    INT YDest,
 +    INT Width,
 +    INT Height,
 +    HDC hDCSrc,
 +    INT XSrc,
 +    INT YSrc,
 +    DWORD ROP,
 +    IN DWORD crBackColor,
 +    IN FLONG fl)
 +{
 +    PDC DCDest;
 +    PDC DCSrc = NULL;
 +    HDC ahDC[2];
 +    PGDIOBJ apObj[2];
 +    PDC_ATTR pdcattr = NULL;
 +    SURFACE *BitmapDest, *BitmapSrc = NULL;
 +    RECTL DestRect, SourceRect;
 +    POINTL SourcePoint;
 +    BOOL Status = FALSE;
 +    EXLATEOBJ exlo;
 +    XLATEOBJ *XlateObj = NULL;
 +    BOOL UsesSource = ROP3_USES_SOURCE(ROP);
 +
 +    DPRINT("Locking DCs\n");
 +    ahDC[0] = hDCDest;
 +    ahDC[1] = hDCSrc ;
 +    GDIOBJ_LockMultipleObjs(2, ahDC, apObj);
 +    DCDest = apObj[0];
 +    DCSrc = apObj[1];
 +
 +    if (NULL == DCDest)
 +    {
 +        if(DCSrc) GDIOBJ_UnlockObjByPtr(&DCSrc->BaseObject);
 +        DPRINT("Invalid destination dc handle (0x%08x) passed to NtGdiBitBlt\n", hDCDest);
 +        return FALSE;
 +    }
 +
 +    if (DCDest->dctype == DC_TYPE_INFO)
 +    {
 +        if(DCSrc) GDIOBJ_UnlockObjByPtr(&DCSrc->BaseObject);
 +        GDIOBJ_UnlockObjByPtr(&DCDest->BaseObject);
 +        /* Yes, Windows really returns TRUE in this case */
 +        return TRUE;
 +    }
 +
 +    if (UsesSource)
 +    {
 +        if (NULL == DCSrc)
 +        {
 +            GDIOBJ_UnlockObjByPtr(&DCDest->BaseObject);
 +            DPRINT("Invalid source dc handle (0x%08x) passed to NtGdiBitBlt\n", hDCSrc);
 +            return FALSE;
 +        }
 +        if (DCSrc->dctype == DC_TYPE_INFO)
 +        {
 +            GDIOBJ_UnlockObjByPtr(&DCDest->BaseObject);
 +            GDIOBJ_UnlockObjByPtr(&DCSrc->BaseObject);
 +            /* Yes, Windows really returns TRUE in this case */
 +            return TRUE;
 +        }
 +    }
 +    else if(DCSrc)
 +    {
 +        DPRINT1("Getting a valid Source handle without using source!!!\n");
 +        GDIOBJ_UnlockObjByPtr(&DCSrc->BaseObject);
 +        DCSrc = NULL ;
 +    }
 +
 +    pdcattr = DCDest->pdcattr;
 +
 +    DestRect.left   = XDest;
 +    DestRect.top    = YDest;
 +    DestRect.right  = XDest+Width;
 +    DestRect.bottom = YDest+Height;
 +    IntLPtoDP(DCDest, (LPPOINT)&DestRect, 2);
 +
 +    DestRect.left   += DCDest->ptlDCOrig.x;
 +    DestRect.top    += DCDest->ptlDCOrig.y;
 +    DestRect.right  += DCDest->ptlDCOrig.x;
 +    DestRect.bottom += DCDest->ptlDCOrig.y;
 +
 +    SourcePoint.x = XSrc;
 +    SourcePoint.y = YSrc;
 +
 +    if (UsesSource)
 +    {
 +        IntLPtoDP(DCSrc, (LPPOINT)&SourcePoint, 1);
 +
 +        SourcePoint.x += DCSrc->ptlDCOrig.x;
 +        SourcePoint.y += DCSrc->ptlDCOrig.y;
 +        /* Calculate Source Rect */
 +        SourceRect.left = SourcePoint.x;
 +        SourceRect.top = SourcePoint.y;
 +        SourceRect.right = SourcePoint.x + DestRect.right - DestRect.left;
 +        SourceRect.bottom = SourcePoint.y + DestRect.bottom - DestRect.top ;
 +    }
 +
 +    /* Prepare blit */
 +    DC_vPrepareDCsForBlit(DCDest, DestRect, DCSrc, SourceRect);
 +
 +    if (pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY))
 +        DC_vUpdateFillBrush(DCDest);
 +
 +    /* Determine surfaces to be used in the bitblt */
 +    BitmapDest = DCDest->dclevel.pSurface;
 +    if (!BitmapDest)
 +        goto cleanup;
 +
 +    if (UsesSource)
 +    {
 +        {
 +            BitmapSrc = DCSrc->dclevel.pSurface;
 +            if (!BitmapSrc)
 +                goto cleanup;
 +        }
 +    }
 +
 +    /* Create the XLATEOBJ. */
 +    if (UsesSource)
 +    {
 +        EXLATEOBJ_vInitXlateFromDCs(&exlo, DCSrc, DCDest);
 +        XlateObj = &exlo.xlo;
 +    }
 +
 +    /* Perform the bitblt operation */
 +    Status = IntEngBitBlt(&BitmapDest->SurfObj,
 +                          BitmapSrc ? &BitmapSrc->SurfObj : NULL,
 +                          NULL,
 +                          DCDest->rosdc.CombinedClip,
 +                          XlateObj,
 +                          &DestRect,
 +                          &SourcePoint,
 +                          NULL,
 +                          &DCDest->eboFill.BrushObject,
 +                          &DCDest->dclevel.pbrFill->ptOrigin,
 +                          ROP3_TO_ROP4(ROP));
 +
 +    if (UsesSource)
 +        EXLATEOBJ_vCleanup(&exlo);
 +cleanup:
 +    DC_vFinishBlit(DCDest, DCSrc);
 +    if (UsesSource)
 +    {
 +        GDIOBJ_UnlockObjByPtr(&DCSrc->BaseObject);
 +    }
 +    GDIOBJ_UnlockObjByPtr(&DCDest->BaseObject);
 +
 +    return Status;
 +}
 +
 +BOOL APIENTRY
 +NtGdiTransparentBlt(
 +    HDC hdcDst,
 +    INT xDst,
 +    INT yDst,
 +    INT cxDst,
 +    INT cyDst,
 +    HDC hdcSrc,
 +    INT xSrc,
 +    INT ySrc,
 +    INT cxSrc,
 +    INT cySrc,
 +    COLORREF TransColor)
 +{
 +    PDC DCDest, DCSrc;
 +    HDC ahDC[2];
 +    PGDIOBJ apObj[2];
 +    RECTL rcDest, rcSrc;
 +    SURFACE *BitmapDest, *BitmapSrc = NULL;
 +    PPALETTE PalSourceGDI;
 +    ULONG TransparentColor = 0;
 +    BOOL Ret = FALSE;
 +    EXLATEOBJ exlo;
 +
 +    DPRINT("Locking DCs\n");
 +    ahDC[0] = hdcDst;
 +    ahDC[1] = hdcSrc ;
 +    GDIOBJ_LockMultipleObjs(2, ahDC, apObj);
 +    DCDest = apObj[0];
 +    DCSrc = apObj[1];
 +
 +    if ((NULL == DCDest) || (NULL == DCSrc))
 +    {
 +        DPRINT1("Invalid dc handle (dest=0x%08x, src=0x%08x) passed to NtGdiAlphaBlend\n", hdcDst, hdcSrc);
 +        SetLastWin32Error(ERROR_INVALID_HANDLE);
 +        if(DCSrc) GDIOBJ_UnlockObjByPtr(&DCSrc->BaseObject);
 +        if(DCDest) GDIOBJ_UnlockObjByPtr(&DCDest->BaseObject);
 +        return FALSE;
 +    }
 +
 +    if (DCDest->dctype == DC_TYPE_INFO || DCDest->dctype == DCTYPE_INFO)
 +    {
 +        GDIOBJ_UnlockObjByPtr(&DCSrc->BaseObject);
 +        GDIOBJ_UnlockObjByPtr(&DCDest->BaseObject);
 +        /* Yes, Windows really returns TRUE in this case */
 +        return TRUE;
 +    }
 +
 +    rcDest.left   = xDst;
 +    rcDest.top    = yDst;
 +    rcDest.right  = rcDest.left + cxDst;
 +    rcDest.bottom = rcDest.top + cyDst;
 +    IntLPtoDP(DCDest, (LPPOINT)&rcDest, 2);
 +
 +    rcDest.left   += DCDest->ptlDCOrig.x;
 +    rcDest.top    += DCDest->ptlDCOrig.y;
 +    rcDest.right  += DCDest->ptlDCOrig.x;
 +    rcDest.bottom += DCDest->ptlDCOrig.y;
 +
 +    rcSrc.left   = xSrc;
 +    rcSrc.top    = ySrc;
 +    rcSrc.right  = rcSrc.left + cxSrc;
 +    rcSrc.bottom = rcSrc.top + cySrc;
 +    IntLPtoDP(DCSrc, (LPPOINT)&rcSrc, 2);
 +
 +    rcSrc.left   += DCSrc->ptlDCOrig.x;
 +    rcSrc.top    += DCSrc->ptlDCOrig.y;
 +    rcSrc.right  += DCSrc->ptlDCOrig.x;
 +    rcSrc.bottom += DCSrc->ptlDCOrig.y;
 +
 +    /* Prepare for blit */
 +    DC_vPrepareDCsForBlit(DCDest, rcDest, DCSrc, rcSrc);
 +
 +    BitmapDest = DCDest->dclevel.pSurface;
 +    if (!BitmapDest)
 +    {
 +        goto done;
 +    }
 +
 +    BitmapSrc = DCSrc->dclevel.pSurface;
 +    if (!BitmapSrc)
 +    {
 +        goto done;
 +    }
 +
 +    if (BitmapSrc->ppal)
 +    {
 +        GDIOBJ_IncrementShareCount(&BitmapSrc->ppal->BaseObject);
 +        PalSourceGDI = BitmapSrc->ppal ;
 +    }
 +    else
 +        PalSourceGDI = PALETTE_ShareLockPalette(pPrimarySurface->devinfo.hpalDefault) ;
 +
 +    if(!PalSourceGDI)
 +    {
 +        SetLastWin32Error(ERROR_INVALID_HANDLE);
 +        goto done;
 +    }
 +
 +    /* Translate Transparent (RGB) Color to the source palette */
 +    EXLATEOBJ_vInitialize(&exlo, &gpalRGB, PalSourceGDI, 0, 0, 0);
 +    TransparentColor = XLATEOBJ_iXlate(&exlo.xlo, (ULONG)TransColor);
 +    EXLATEOBJ_vCleanup(&exlo);
 +    PALETTE_ShareUnlockPalette(PalSourceGDI);
 +
 +    EXLATEOBJ_vInitXlateFromDCs(&exlo, DCSrc, DCDest);
 +
 +    Ret = IntEngTransparentBlt(&BitmapDest->SurfObj, &BitmapSrc->SurfObj,
 +        DCDest->rosdc.CombinedClip, &exlo.xlo, &rcDest, &rcSrc,
 +        TransparentColor, 0);
 +
 +    EXLATEOBJ_vCleanup(&exlo);
 +
 +done:
 +    DC_vFinishBlit(DCDest, DCSrc);
 +    GDIOBJ_UnlockObjByPtr(&DCDest->BaseObject);
 +    GDIOBJ_UnlockObjByPtr(&DCSrc->BaseObject);
 +
 +    return Ret;
 +}
 +
 +/***********************************************************************
 +* MaskBlt
 +* Ported from WINE by sedwards 11-4-03
 +*
 +* Someone thought it would be faster to do it here and then switch back
 +* to GDI32. I dunno. Write a test and let me know.
 +* A. It should be in here!
 +*/
 +
++static const DWORD ROP3Table[256] =
++{
++  0x000042, 0x010289, 0x020C89, 0x0300AA, 0x040C88, 0x0500A9, 0x060865, 0x0702C5,
++  0x080F08, 0x090245, 0x0A0329, 0x0B0B2A, 0x0C0324, 0x0D0B25, 0x0E08A5, 0x0F0001,
++  0x100C85, 0x1100A6, 0x120868, 0x1302C8, 0x140869, 0x1502C9, 0x165CCA, 0x171D54,
++  0x180D59, 0x191CC8, 0x1A06C5, 0x1B0768, 0x1C06CA, 0x1D0766, 0x1E01A5, 0x1F0385,
++  0x200F09, 0x210248, 0x220326, 0x230B24, 0x240D55, 0x251CC5, 0x2606C8, 0x271868,
++  0x280369, 0x2916CA, 0x2A0CC9, 0x2B1D58, 0x2C0784, 0x2D060A, 0x2E064A, 0x2F0E2A,
++  0x30032A, 0x310B28, 0x320688, 0x330008, 0x3406C4, 0x351864, 0x3601A8, 0x370388,
++  0x38078A, 0x390604, 0x3A0644, 0x3B0E24, 0x3C004A, 0x3D18A4, 0x3E1B24, 0x3F00EA,
++  0x400F0A, 0x410249, 0x420D5D, 0x431CC4, 0x440328, 0x450B29, 0x4606C6, 0x47076A,
++  0x480368, 0x4916C5, 0x4A0789, 0x4B0605, 0x4C0CC8, 0x4D1954, 0x4E0645, 0x4F0E25,
++  0x500325, 0x510B26, 0x5206C9, 0x530764, 0x5408A9, 0x550009, 0x5601A9, 0x570389,
++  0x580785, 0x590609, 0x5A0049, 0x5B18A9, 0x5C0649, 0x5D0E29, 0x5E1B29, 0x5F00E9,
++  0x600365, 0x6116C6, 0x620786, 0x630608, 0x640788, 0x650606, 0x660046, 0x6718A8,
++  0x6858A6, 0x690145, 0x6A01E9, 0x6B178A, 0x6C01E8, 0x6D1785, 0x6E1E28, 0x6F0C65,
++  0x700CC5, 0x711D5C, 0x720648, 0x730E28, 0x740646, 0x750E26, 0x761B28, 0x7700E6,
++  0x7801E5, 0x791786, 0x7A1E29, 0x7B0C68, 0x7C1E24, 0x7D0C69, 0x7E0955, 0x7F03C9,
++  0x8003E9, 0x810975, 0x820C49, 0x831E04, 0x840C48, 0x851E05, 0x8617A6, 0x8701C5,
++  0x8800C6, 0x891B08, 0x8A0E06, 0x8B0666, 0x8C0E08, 0x8D0668, 0x8E1D7C, 0x8F0CE5,
++  0x900C45, 0x911E08, 0x9217A9, 0x9301C4, 0x9417AA, 0x9501C9, 0x960169, 0x97588A,
++  0x981888, 0x990066, 0x9A0709, 0x9B07A8, 0x9C0704, 0x9D07A6, 0x9E16E6, 0x9F0345,
++  0xA000C9, 0xA11B05, 0xA20E09, 0xA30669, 0xA41885, 0xA50065, 0xA60706, 0xA707A5,
++  0xA803A9, 0xA90189, 0xAA0029, 0xAB0889, 0xAC0744, 0xAD06E9, 0xAE0B06, 0xAF0229,
++  0xB00E05, 0xB10665, 0xB21974, 0xB30CE8, 0xB4070A, 0xB507A9, 0xB616E9, 0xB70348,
++  0xB8074A, 0xB906E6, 0xBA0B09, 0xBB0226, 0xBC1CE4, 0xBD0D7D, 0xBE0269, 0xBF08C9,
++  0xC000CA, 0xC11B04, 0xC21884, 0xC3006A, 0xC40E04, 0xC50664, 0xC60708, 0xC707AA,
++  0xC803A8, 0xC90184, 0xCA0749, 0xCB06E4, 0xCC0020, 0xCD0888, 0xCE0B08, 0xCF0224,
++  0xD00E0A, 0xD1066A, 0xD20705, 0xD307A4, 0xD41D78, 0xD50CE9, 0xD616EA, 0xD70349,
++  0xD80745, 0xD906E8, 0xDA1CE9, 0xDB0D75, 0xDC0B04, 0xDD0228, 0xDE0268, 0xDF08C8,
++  0xE003A5, 0xE10185, 0xE20746, 0xE306EA, 0xE40748, 0xE506E5, 0xE61CE8, 0xE70D79,
++  0xE81D74, 0xE95CE6, 0xEA02E9, 0xEB0849, 0xEC02E8, 0xED0848, 0xEE0086, 0xEF0A08,
++  0xF00021, 0xF10885, 0xF20B05, 0xF3022A, 0xF40B0A, 0xF50225, 0xF60265, 0xF708C5,
++  0xF802E5, 0xF90845, 0xFA0089, 0xFB0A09, 0xFC008A, 0xFD0A0A, 0xFE02A9, 0xFF0062,
++};
++
 +static __inline BYTE
 +SwapROP3_SrcDst(BYTE bRop3)
 +{
 +    return (bRop3 & 0x99) | ((bRop3 & 0x22) << 1) | ((bRop3 & 0x44) >> 1);
 +}
 +
 +#define FRGND_ROP3(ROP4)    ((ROP4) & 0x00FFFFFF)
 +#define BKGND_ROP3(ROP4)    (ROP3Table[(SwapROP3_SrcDst((ROP4)>>24)) & 0xFF])
 +#define DSTCOPY    0x00AA0029
 +#define DSTERASE    0x00220326 /* dest = dest & (~src) : DSna */
 +
++/* NOTE: An alternative algorithm could use a pattern brush, created from
++ * the mask bitmap and then use raster operation 0xCA to combine the fore
++ * and background bitmaps. In this case erasing the bits beforehand would be
++ * unneccessary. On the other hand the Operation does not provide an optimized
++ * version in the DIB code, while SRCAND and SRCPAINT do.
++ * A fully correct implementation would call Eng/DrvBitBlt, but our
++ * EngBitBlt completely ignores the mask surface.
++ *
++ * Msk Fg Bk => x
++ *  P  S  D        DPSDxax
++ * ------------------------------------------
++ *  0  0  0     0  0000xax = 000ax = 00x = 0
++ *  0  0  1     1  1001xax = 101ax = 10x = 1
++ *  0  1  0     0  0010xax = 001ax = 00x = 0
++ *  0  1  1     1  1011xax = 100ax = 10x = 1
++ *  1  0  0     0  0100xax = 010ax = 00x = 0
++ *  1  0  1     0  1101xax = 111ax = 11x = 0
++ *  1  1  0     1  0110xax = 011ax = 01x = 1
++ *  1  1  1     1  1111xax = 110ax = 10x = 1
++ * 
++ * Operation index = 11001010 = 0xCA = PSaDPnao = DPSDxax 
++ *                                     ^ no, this is not random letters, its reverse Polish notation
++ */
++
 +BOOL APIENTRY
 +NtGdiMaskBlt(
 +    HDC hdcDest,
 +    INT nXDest,
 +    INT nYDest,
 +    INT nWidth,
 +    INT nHeight,
 +    HDC hdcSrc,
 +    INT nXSrc,
 +    INT nYSrc,
 +    HBITMAP hbmMask,
 +    INT xMask,
 +    INT yMask,
 +    DWORD dwRop,
 +    IN DWORD crBackColor)
 +{
-         return NtGdiBitBlt(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, FRGND_ROP3(dwRop), 0, 0);
-     /* 1. make mask bitmap's dc */
-     hDCMask = NtGdiCreateCompatibleDC(hdcDest);
-     hOldMaskBitmap = (HBITMAP)NtGdiSelectBitmap(hDCMask, hbmMask);
-     /* 2. make masked Background bitmap */
-     /* 2.1 make bitmap */
-     hDC1 = NtGdiCreateCompatibleDC(hdcDest);
-     hBitmap2 = NtGdiCreateCompatibleBitmap(hdcDest, nWidth, nHeight);
-     hOldBitmap2 = (HBITMAP)NtGdiSelectBitmap(hDC1, hBitmap2);
-     /* 2.2 draw dest bitmap and mask */
-     NtGdiBitBlt(hDC1, 0, 0, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, SRCCOPY, 0, 0);
-     NtGdiBitBlt(hDC1, 0, 0, nWidth, nHeight, hdcDest, nXDest, nYDest, BKGND_ROP3(dwRop), 0, 0);
-     NtGdiBitBlt(hDC1, 0, 0, nWidth, nHeight, hDCMask, xMask, yMask, DSTERASE, 0, 0);
-     /* 3. make masked Foreground bitmap */
-     /* 3.1 make bitmap */
-     hDC2 = NtGdiCreateCompatibleDC(hdcDest);
-     hBitmap3 = NtGdiCreateCompatibleBitmap(hdcDest, nWidth, nHeight);
-     hOldBitmap3 = (HBITMAP)NtGdiSelectBitmap(hDC2, hBitmap3);
-     /* 3.2 draw src bitmap and mask */
-     NtGdiBitBlt(hDC2, 0, 0, nWidth, nHeight, hdcDest, nXDest, nYDest, SRCCOPY, 0, 0);
-     NtGdiBitBlt(hDC2, 0, 0, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, FRGND_ROP3(dwRop), 0,0);
-     NtGdiBitBlt(hDC2, 0, 0, nWidth, nHeight, hDCMask, xMask, yMask, SRCAND, 0, 0);
-     /* 4. combine both and copy the result to hdcDest */
-     NtGdiBitBlt(hDC1, 0, 0, nWidth, nHeight, hDC2, 0, 0, SRCPAINT, 0, 0);
-     NtGdiBitBlt(hdcDest, nXDest, nYDest, nWidth, nHeight, hDC1, 0, 0, SRCCOPY, 0, 0);
-     /* 5. restore all objects */
-     NtGdiSelectBitmap(hDCMask, hOldMaskBitmap);
-     NtGdiSelectBitmap(hDC1, hOldBitmap2);
-     NtGdiSelectBitmap(hDC2, hOldBitmap3);
-     /* 6. delete all temp objects */
-     GreDeleteObject(hBitmap2);
-     GreDeleteObject(hBitmap3);
-     NtGdiDeleteObjectApp(hDC1);
-     NtGdiDeleteObjectApp(hDC2);
-     NtGdiDeleteObjectApp(hDCMask);
++    HBITMAP hbmFore, hbmBack;
++    HDC hdcMask, hdcFore, hdcBack;
++    PDC pdc;
++    HBRUSH hbr;
++    COLORREF crFore, crBack;
 +
 +    if (!hbmMask)
++        return NtGdiBitBlt(hdcDest,
++                           nXDest,
++                           nYDest,
++                           nWidth,
++                           nHeight,
++                           hdcSrc,
++                           nXSrc,
++                           nYSrc,
++                           FRGND_ROP3(dwRop),
++                           crBackColor,
++                           0);
++
++    /* Lock the dest DC */
++    pdc = DC_LockDc(hdcDest);
++    if (!pdc) return FALSE;
++
++    /* Get brush and colors from dest dc */
++    hbr = pdc->pdcattr->hbrush;
++    crFore = pdc->pdcattr->crForegroundClr;
++    crBack = pdc->pdcattr->crBackgroundClr;
++
++    /* Unlock the DC */
++    DC_UnlockDc(pdc);
++
++    /* 1. Create mask bitmap's dc */
++    hdcMask = NtGdiCreateCompatibleDC(hdcDest);
++    NtGdiSelectBitmap(hdcMask, hbmMask);
++
++    /* 2. Create masked Background bitmap */
++
++    /* 2.1 Create bitmap */
++    hdcBack = NtGdiCreateCompatibleDC(hdcDest);
++    hbmBack = NtGdiCreateCompatibleBitmap(hdcDest, nWidth, nHeight);
++    NtGdiSelectBitmap(hdcBack, hbmBack);
++
++    /* 2.2 Copy source bitmap */
++    NtGdiSelectBrush(hdcBack, hbr);
++    IntGdiSetBkColor(hdcBack, crBack);
++    IntGdiSetTextColor(hdcBack, crFore);
++    NtGdiBitBlt(hdcBack, 0, 0, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, SRCCOPY, 0, 0);
++
++    /* 2.3 Do the background rop */
++    NtGdiBitBlt(hdcBack, 0, 0, nWidth, nHeight, hdcDest, nXDest, nYDest, BKGND_ROP3(dwRop), 0, 0);
++
++    /* 2.4 Erase the foreground pixels */
++    IntGdiSetBkColor(hdcBack, 0xffffffff);
++    IntGdiSetTextColor(hdcBack, 0);
++    NtGdiBitBlt(hdcBack, 0, 0, nWidth, nHeight, hdcMask, xMask, yMask, SRCAND, 0, 0);
++
++    /* 3. Create masked Foreground bitmap */
++
++    /* 3.1 Create bitmap */
++    hdcFore = NtGdiCreateCompatibleDC(hdcDest);
++    hbmFore = NtGdiCreateCompatibleBitmap(hdcDest, nWidth, nHeight);
++    NtGdiSelectBitmap(hdcFore, hbmFore);
++
++    /* 3.2 Copy the dest bitmap */
++    NtGdiSelectBrush(hdcFore, hbr);
++    IntGdiSetBkColor(hdcFore, crBack);
++    IntGdiSetTextColor(hdcFore, crFore);
++    NtGdiBitBlt(hdcFore, 0, 0, nWidth, nHeight, hdcDest, nXDest, nYDest, SRCCOPY, 0, 0);
++
++    /* 2.3 Do the foreground rop */
++    NtGdiBitBlt(hdcFore, 0, 0, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, FRGND_ROP3(dwRop), 0,0);
++
++    /* 2.4 Erase the background pixels */
++    IntGdiSetBkColor(hdcFore, 0);
++    IntGdiSetTextColor(hdcFore, 0xffffffff);
++    NtGdiBitBlt(hdcFore, 0, 0, nWidth, nHeight, hdcMask, xMask, yMask, SRCAND, 0, 0);
++
++    /* 3. Combine the fore and background into the background bitmap */
++    NtGdiBitBlt(hdcBack, 0, 0, nWidth, nHeight, hdcFore, 0, 0, SRCPAINT, 0, 0);
++
++    /* 4. Copy the result to hdcDest */
++    NtGdiBitBlt(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcBack, 0, 0, SRCCOPY, 0, 0);
++
++    /* 5. delete all temp objects */
++    NtGdiDeleteObjectApp(hdcBack);
++    NtGdiDeleteObjectApp(hdcFore);
++    NtGdiDeleteObjectApp(hdcMask);
++    GreDeleteObject(hbmFore);
++    GreDeleteObject(hbmBack);
 +
 +    return TRUE;
 +}
 +
 +BOOL
 +APIENTRY
 +NtGdiPlgBlt(
 +    IN HDC hdcTrg,
 +    IN LPPOINT pptlTrg,
 +    IN HDC hdcSrc,
 +    IN INT xSrc,
 +    IN INT ySrc,
 +    IN INT cxSrc,
 +    IN INT cySrc,
 +    IN HBITMAP hbmMask,
 +    IN INT xMask,
 +    IN INT yMask,
 +    IN DWORD crBackColor)
 +{
 +    UNIMPLEMENTED;
 +    return FALSE;
 +}
 +
 +BOOL APIENTRY
 +GreStretchBltMask(
 +    HDC hDCDest,
 +    INT XOriginDest,
 +    INT YOriginDest,
 +    INT WidthDest,
 +    INT HeightDest,
 +    HDC hDCSrc,
 +    INT XOriginSrc,
 +    INT YOriginSrc,
 +    INT WidthSrc,
 +    INT HeightSrc,
 +    DWORD ROP,
 +    IN DWORD dwBackColor,
 +    HDC hDCMask,
 +    INT XOriginMask,
 +    INT YOriginMask)
 +{
 +    PDC DCDest;
 +    PDC DCSrc  = NULL;
 +    PDC DCMask = NULL;
 +    HDC ahDC[3];
 +    PGDIOBJ apObj[3];
 +    PDC_ATTR pdcattr;
 +    SURFACE *BitmapDest, *BitmapSrc = NULL;
 +    SURFACE *BitmapMask = NULL;
 +    RECTL DestRect;
 +    RECTL SourceRect;
 +    POINTL MaskPoint;
 +    BOOL Status = FALSE;
 +    EXLATEOBJ exlo;
 +    XLATEOBJ *XlateObj = NULL;
 +    POINTL BrushOrigin;
 +    BOOL UsesSource = ROP3_USES_SOURCE(ROP);
 +
 +    if (0 == WidthDest || 0 == HeightDest || 0 == WidthSrc || 0 == HeightSrc)
 +    {
 +        SetLastWin32Error(ERROR_INVALID_PARAMETER);
 +        return FALSE;
 +    }
 +
 +    DPRINT("Locking DCs\n");
 +    ahDC[0] = hDCDest;
 +    ahDC[1] = hDCSrc ;
 +    ahDC[2] = hDCMask ;
 +    GDIOBJ_LockMultipleObjs(3, ahDC, apObj);
 +    DCDest = apObj[0];
 +    DCSrc = apObj[1];
 +    DCMask = apObj[2];
 +
 +    if (NULL == DCDest)
 +    {
 +        if(DCSrc) GDIOBJ_UnlockObjByPtr(&DCSrc->BaseObject);
 +        if(DCMask) GDIOBJ_UnlockObjByPtr(&DCMask->BaseObject);
 +        DPRINT("Invalid destination dc handle (0x%08x) passed to NtGdiBitBlt\n", hDCDest);
 +        return FALSE;
 +    }
 +
 +    if (DCDest->dctype == DC_TYPE_INFO)
 +    {
 +        if(DCSrc) GDIOBJ_UnlockObjByPtr(&DCSrc->BaseObject);
 +        if(DCMask) GDIOBJ_UnlockObjByPtr(&DCMask->BaseObject);
 +        GDIOBJ_UnlockObjByPtr(&DCDest->BaseObject);
 +        /* Yes, Windows really returns TRUE in this case */
 +        return TRUE;
 +    }
 +
 +    if (UsesSource)
 +    {
 +        if (NULL == DCSrc)
 +        {
 +            GDIOBJ_UnlockObjByPtr(&DCDest->BaseObject);
 +            if(DCMask) GDIOBJ_UnlockObjByPtr(&DCMask->BaseObject);
 +            DPRINT("Invalid source dc handle (0x%08x) passed to NtGdiBitBlt\n", hDCSrc);
 +            return FALSE;
 +        }
 +        if (DCSrc->dctype == DC_TYPE_INFO)
 +        {
 +            GDIOBJ_UnlockObjByPtr(&DCDest->BaseObject);
 +            GDIOBJ_UnlockObjByPtr(&DCSrc->BaseObject);
 +            if(DCMask) GDIOBJ_UnlockObjByPtr(&DCMask->BaseObject);
 +            /* Yes, Windows really returns TRUE in this case */
 +            return TRUE;
 +        }
 +    }
 +    else if(DCSrc)
 +    {
 +        DPRINT1("Getting a valid Source handle without using source!!!\n");
 +        GDIOBJ_UnlockObjByPtr(&DCSrc->BaseObject);
 +        DCSrc = NULL ;
 +    }
 +
 +    pdcattr = DCDest->pdcattr;
 +
 +    DestRect.left   = XOriginDest;
 +    DestRect.top    = YOriginDest;
 +    DestRect.right  = XOriginDest+WidthDest;
 +    DestRect.bottom = YOriginDest+HeightDest;
 +    IntLPtoDP(DCDest, (LPPOINT)&DestRect, 2);
 +
 +    DestRect.left   += DCDest->ptlDCOrig.x;
 +    DestRect.top    += DCDest->ptlDCOrig.y;
 +    DestRect.right  += DCDest->ptlDCOrig.x;
 +    DestRect.bottom += DCDest->ptlDCOrig.y;
 +
 +    SourceRect.left   = XOriginSrc;
 +    SourceRect.top    = YOriginSrc;
 +    SourceRect.right  = XOriginSrc+WidthSrc;
 +    SourceRect.bottom = YOriginSrc+HeightSrc;
 +
 +    if (UsesSource)
 +    {
 +        IntLPtoDP(DCSrc, (LPPOINT)&SourceRect, 2);
 +
 +        SourceRect.left   += DCSrc->ptlDCOrig.x;
 +        SourceRect.top    += DCSrc->ptlDCOrig.y;
 +        SourceRect.right  += DCSrc->ptlDCOrig.x;
 +        SourceRect.bottom += DCSrc->ptlDCOrig.y;
 +    }
 +
 +    BrushOrigin.x = 0;
 +    BrushOrigin.y = 0;
 +
 +    /* Only prepare Source and Dest, hdcMask represents a DIB */
 +    DC_vPrepareDCsForBlit(DCDest, DestRect, DCSrc, SourceRect);
 +
 +    if (pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY))
 +        DC_vUpdateFillBrush(DCDest);
 +
 +    /* Determine surfaces to be used in the bitblt */
 +    BitmapDest = DCDest->dclevel.pSurface;
 +    if (BitmapDest == NULL)
 +        goto failed;
 +    if (UsesSource)
 +    {
 +        BitmapSrc = DCSrc->dclevel.pSurface;
 +        if (BitmapSrc == NULL)
 +            goto failed;
 +
 +        /* Create the XLATEOBJ. */
 +        EXLATEOBJ_vInitXlateFromDCs(&exlo, DCSrc, DCDest);
 +        XlateObj = &exlo.xlo;
 +    }
 +
 +    /* Offset the brush */
 +    BrushOrigin.x += DCDest->ptlDCOrig.x;
 +    BrushOrigin.y += DCDest->ptlDCOrig.y;
 +
 +    /* Make mask surface for source surface */
 +    if (BitmapSrc && DCMask)
 +    {
 +        BitmapMask = DCMask->dclevel.pSurface;
 +        if (BitmapMask &&
 +            (BitmapMask->SurfObj.sizlBitmap.cx < WidthSrc ||
 +             BitmapMask->SurfObj.sizlBitmap.cy < HeightSrc))
 +        {
 +            DPRINT1("%dx%d mask is smaller than %dx%d bitmap\n",
 +                    BitmapMask->SurfObj.sizlBitmap.cx, BitmapMask->SurfObj.sizlBitmap.cy,
 +                    WidthSrc, HeightSrc);
 +            EXLATEOBJ_vCleanup(&exlo);
 +            goto failed;
 +        }
 +        /* Create mask offset point */
 +        MaskPoint.x = XOriginMask;
 +        MaskPoint.y = YOriginMask;
 +        IntLPtoDP(DCMask, &MaskPoint, 1);
 +        MaskPoint.x += DCMask->ptlDCOrig.x;
 +        MaskPoint.y += DCMask->ptlDCOrig.x;
 +    }
 +
 +    /* Perform the bitblt operation */
 +    Status = IntEngStretchBlt(&BitmapDest->SurfObj,
 +                              &BitmapSrc->SurfObj,
 +                              BitmapMask ? &BitmapMask->SurfObj : NULL,
 +                              DCDest->rosdc.CombinedClip,
 +                              XlateObj,
 +                              &DestRect,
 +                              &SourceRect,
 +                              BitmapMask ? &MaskPoint : NULL,
 +                              &DCDest->eboFill.BrushObject,
 +                              &BrushOrigin,
 +                              ROP3_TO_ROP4(ROP));
 +    if (UsesSource)
 +    {
 +        EXLATEOBJ_vCleanup(&exlo);
 +    }
 +
 +failed:
 +    DC_vFinishBlit(DCDest, DCSrc);
 +    if (UsesSource)
 +    {
 +        DC_UnlockDc(DCSrc);
 +    }
 +    if (DCMask)
 +    {
 +        DC_UnlockDc(DCMask);
 +    }
 +    DC_UnlockDc(DCDest);
 +
 +    return Status;
 +}
 +
 +
 +BOOL APIENTRY
 +NtGdiStretchBlt(
 +    HDC hDCDest,
 +    INT XOriginDest,
 +    INT YOriginDest,
 +    INT WidthDest,
 +    INT HeightDest,
 +    HDC hDCSrc,
 +    INT XOriginSrc,
 +    INT YOriginSrc,
 +    INT WidthSrc,
 +    INT HeightSrc,
 +    DWORD ROP,
 +    IN DWORD dwBackColor)
 +{
 +    return GreStretchBltMask(
 +                hDCDest,
 +                XOriginDest,
 +                YOriginDest,
 +                WidthDest,
 +                HeightDest,
 +                hDCSrc,
 +                XOriginSrc,
 +                YOriginSrc,
 +                WidthSrc,
 +                HeightSrc,
 +                ROP,
 +                dwBackColor,
 +                NULL,
 +                0,
 +                0);
 +}
 +
 +
 +BOOL FASTCALL
 +IntPatBlt(
 +    PDC pdc,
 +    INT XLeft,
 +    INT YLeft,
 +    INT Width,
 +    INT Height,
 +    DWORD dwRop,
 +    PBRUSH pbrush)
 +{
 +    RECTL DestRect;
 +    SURFACE *psurf;
 +    EBRUSHOBJ eboFill ;
 +    POINTL BrushOrigin;
 +    BOOL ret;
 +
 +    ASSERT(pbrush);
 +
 +    if (pbrush->flAttrs & GDIBRUSH_IS_NULL)
 +    {
 +        return TRUE;
 +    }
 +
 +    if (Width > 0)
 +    {
 +        DestRect.left = XLeft;
 +        DestRect.right = XLeft + Width;
 +    }
 +    else
 +    {
 +        DestRect.left = XLeft + Width + 1;
 +        DestRect.right = XLeft + 1;
 +    }
 +
 +    if (Height > 0)
 +    {
 +        DestRect.top = YLeft;
 +        DestRect.bottom = YLeft + Height;
 +    }
 +    else
 +    {
 +        DestRect.top = YLeft + Height + 1;
 +        DestRect.bottom = YLeft + 1;
 +    }
 +
 +    IntLPtoDP(pdc, (LPPOINT)&DestRect, 2);
 +
 +    DestRect.left   += pdc->ptlDCOrig.x;
 +    DestRect.top    += pdc->ptlDCOrig.y;
 +    DestRect.right  += pdc->ptlDCOrig.x;
 +    DestRect.bottom += pdc->ptlDCOrig.y;
 +
 +    BrushOrigin.x = pbrush->ptOrigin.x + pdc->ptlDCOrig.x;
 +    BrushOrigin.y = pbrush->ptOrigin.y + pdc->ptlDCOrig.y;
 +
 +    DC_vPrepareDCsForBlit(pdc, DestRect, NULL, DestRect);
 +
 +    psurf = pdc->dclevel.pSurface;
 +
 +    if (pdc->pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY))
 +        DC_vUpdateFillBrush(pdc);
 +
 +    EBRUSHOBJ_vInit(&eboFill, pbrush, pdc);
 +
 +    ret = IntEngBitBlt(
 +        &psurf->SurfObj,
 +        NULL,
 +        NULL,
 +        pdc->rosdc.CombinedClip,
 +        NULL,
 +        &DestRect,
 +        NULL,
 +        NULL,
 +        &eboFill.BrushObject,
 +        &BrushOrigin,
 +        ROP3_TO_ROP4(dwRop));
 +
 +    DC_vFinishBlit(pdc, NULL);
 +
 +    EBRUSHOBJ_vCleanup(&eboFill);
 +
 +    return ret;
 +}
 +
 +BOOL FASTCALL
 +IntGdiPolyPatBlt(
 +    HDC hDC,
 +    DWORD dwRop,
 +    PPATRECT pRects,
 +    INT cRects,
 +    ULONG Reserved)
 +{
 +    INT i;
 +    PBRUSH pbrush;
 +    PDC pdc;
 +
 +    pdc = DC_LockDc(hDC);
 +    if (!pdc)
 +    {
 +        SetLastWin32Error(ERROR_INVALID_HANDLE);
 +        return FALSE;
 +    }
 +
 +    if (pdc->dctype == DC_TYPE_INFO)
 +    {
 +        DC_UnlockDc(pdc);
 +        /* Yes, Windows really returns TRUE in this case */
 +        return TRUE;
 +    }
 +
 +    for (i = 0; i < cRects; i++)
 +    {
 +        pbrush = BRUSH_LockBrush(pRects->hBrush);
 +        if(pbrush != NULL)
 +        {
 +            IntPatBlt(
 +                pdc,
 +                pRects->r.left,
 +                pRects->r.top,
 +                pRects->r.right,
 +                pRects->r.bottom,
 +                dwRop,
 +                pbrush);
 +            BRUSH_UnlockBrush(pbrush);
 +        }
 +        pRects++;
 +    }
 +
 +    DC_UnlockDc(pdc);
 +
 +    return TRUE;
 +}
 +
 +
 +BOOL APIENTRY
 +NtGdiPatBlt(
 +    HDC hDC,
 +    INT XLeft,
 +    INT YLeft,
 +    INT Width,
 +    INT Height,
 +    DWORD ROP)
 +{
 +    PBRUSH pbrush;
 +    DC *dc;
 +    PDC_ATTR pdcattr;
 +    BOOL ret;
 +
 +    BOOL UsesSource = ROP3_USES_SOURCE(ROP);
 +    if (UsesSource)
 +    {
 +        /* in this case we call on GdiMaskBlt */
 +        return NtGdiMaskBlt(hDC, XLeft, YLeft, Width, Height, 0,0,0,0,0,0,ROP,0);
 +    }
 +
 +    dc = DC_LockDc(hDC);
 +    if (dc == NULL)
 +    {
 +        SetLastWin32Error(ERROR_INVALID_HANDLE);
 +        return FALSE;
 +    }
 +    if (dc->dctype == DC_TYPE_INFO)
 +    {
 +        DC_UnlockDc(dc);
 +        /* Yes, Windows really returns TRUE in this case */
 +        return TRUE;
 +    }
 +
 +    pdcattr = dc->pdcattr;
 +
 +    if (pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY))
 +        DC_vUpdateFillBrush(dc);
 +
 +    pbrush = BRUSH_LockBrush(pdcattr->hbrush);
 +    if (pbrush == NULL)
 +    {
 +        SetLastWin32Error(ERROR_INVALID_HANDLE);
 +        DC_UnlockDc(dc);
 +        return FALSE;
 +    }
 +
 +    ret = IntPatBlt(dc, XLeft, YLeft, Width, Height, ROP, pbrush);
 +
 +    BRUSH_UnlockBrush(pbrush);
 +    DC_UnlockDc(dc);
 +
 +    return ret;
 +}
 +
 +BOOL APIENTRY
 +NtGdiPolyPatBlt(
 +    HDC hDC,
 +    DWORD dwRop,
 +    IN PPOLYPATBLT pRects,
 +    IN DWORD cRects,
 +    IN DWORD Mode)
 +{
 +    PPATRECT rb = NULL;
 +    NTSTATUS Status = STATUS_SUCCESS;
 +    BOOL Ret;
 +
 +    if (cRects > 0)
 +    {
 +        rb = ExAllocatePoolWithTag(PagedPool, sizeof(PATRECT) * cRects, TAG_PATBLT);
 +        if (!rb)
 +        {
 +            SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
 +            return FALSE;
 +        }
 +        _SEH2_TRY
 +        {
 +            ProbeForRead(pRects,
 +                cRects * sizeof(PATRECT),
 +                1);
 +            RtlCopyMemory(rb,
 +                pRects,
 +                cRects * sizeof(PATRECT));
 +        }
 +        _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
 +        {
 +            Status = _SEH2_GetExceptionCode();
 +        }
 +        _SEH2_END;
 +
 +        if (!NT_SUCCESS(Status))
 +        {
 +            ExFreePoolWithTag(rb, TAG_PATBLT);
 +            SetLastNtError(Status);
 +            return FALSE;
 +        }
 +    }
 +
 +    Ret = IntGdiPolyPatBlt(hDC, dwRop, rb, cRects, Mode);
 +
 +    if (cRects > 0)
 +        ExFreePoolWithTag(rb, TAG_PATBLT);
 +
 +    return Ret;
 +}
index 163fda6,0000000..3c9f0e2
mode 100644,000000..100644
--- /dev/null
@@@ -1,1077 -1,0 +1,1079 @@@
 +/*
 + *  ReactOS W32 Subsystem
 + *  Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
 + *
 + *  This program is free software; you can redistribute it and/or modify
 + *  it under the terms of the GNU General Public License as published by
 + *  the Free Software Foundation; either version 2 of the License, or
 + *  (at your option) any later version.
 + *
 + *  This program is distributed in the hope that it will be useful,
 + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 + *  GNU General Public License for more details.
 + *
 + *  You should have received a copy of the GNU General Public License along
 + *  with this program; if not, write to the Free Software Foundation, Inc.,
 + *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 + */
 +
 +#include <win32k.h>
 +
 +#define NDEBUG
 +#include <debug.h>
 +
 +LONG APIENTRY
 +IntSetBitmapBits(
 +    PSURFACE psurf,
 +    DWORD Bytes,
 +    IN PBYTE Bits)
 +{
 +    /* Don't copy more bytes than the buffer has */
 +    Bytes = min(Bytes, psurf->SurfObj.cjBits);
 +
 +    RtlCopyMemory(psurf->SurfObj.pvBits, Bits, Bytes);
 +
 +    return Bytes;
 +}
 +
 +void
 +NTAPI
 +UnsafeSetBitmapBits(
 +    PSURFACE psurf,
 +    IN ULONG cjBits,
 +    IN PVOID pvBits)
 +{
 +    PUCHAR pjDst, pjSrc;
 +    LONG lDeltaDst, lDeltaSrc;
 +    ULONG nWidth, nHeight, cBitsPixel;
 +
 +    nWidth = psurf->SurfObj.sizlBitmap.cx;
 +    nHeight = psurf->SurfObj.sizlBitmap.cy;
 +    cBitsPixel = BitsPerFormat(psurf->SurfObj.iBitmapFormat);
 +
 +    /* Get pointers */
 +    pjDst = psurf->SurfObj.pvScan0;
 +    pjSrc = pvBits;
 +    lDeltaDst = psurf->SurfObj.lDelta;
 +    lDeltaSrc = BITMAP_GetWidthBytes(nWidth, cBitsPixel);
 +
 +    while (nHeight--)
 +    {
 +        /* Copy one line */
 +        memcpy(pjDst, pjSrc, lDeltaSrc);
 +        pjSrc += lDeltaSrc;
 +        pjDst += lDeltaDst;
 +    }
 +
 +}
 +
 +HBITMAP
 +APIENTRY
 +GreCreateBitmapEx(
 +    IN INT nWidth,
 +    IN INT nHeight,
 +    IN ULONG cjWidthBytes,
 +    IN ULONG iFormat,
 +    IN USHORT fjBitmap,
 +    IN ULONG cjSizeImage,
 +    IN OPTIONAL PVOID pvBits,
 +      IN FLONG flags)
 +{
 +    PSURFACE psurf;
 +    SURFOBJ *pso;
 +    HBITMAP hbmp;
 +    PVOID pvCompressedBits;
 +    SIZEL sizl;
 +
 +    /* Verify format */
 +    if (iFormat < BMF_1BPP || iFormat > BMF_PNG) return NULL;
 +
 +    /* Allocate a surface */
 +    psurf = SURFACE_AllocSurface(STYPE_BITMAP, nWidth, nHeight, iFormat);
 +    if (!psurf)
 +    {
 +        DPRINT1("SURFACE_AllocSurface failed.\n");
 +        return NULL;
 +    }
 +
 +    /* Get the handle for the bitmap and the surfobj */
 +    hbmp = (HBITMAP)psurf->SurfObj.hsurf;
 +    pso = &psurf->SurfObj;
 +
 +    /* The infamous RLE hack */
 +    if (iFormat == BMF_4RLE)
 +    {
 +        sizl.cx = nWidth; sizl.cy = nHeight;
 +        pvCompressedBits = pvBits;
 +        pvBits = EngAllocMem(FL_ZERO_MEMORY, pso->cjBits, TAG_DIB);
 +        Decompress4bpp(sizl, pvCompressedBits, pvBits, pso->lDelta);
 +        fjBitmap |= BMF_RLE_HACK;
 +    }
 +    else if (iFormat == BMF_8RLE)
 +    {
 +        sizl.cx = nWidth; sizl.cy = nHeight;
 +        pvCompressedBits = pvBits;
 +        pvBits = EngAllocMem(FL_ZERO_MEMORY, pso->cjBits, TAG_DIB);
 +        Decompress8bpp(sizl, pvCompressedBits, pvBits, pso->lDelta);
 +        fjBitmap |= BMF_RLE_HACK;
 +    }
 +
 +      /* Mark as API bitmap */
 +      psurf->flags |= (flags | API_BITMAP);
 +
 +    /* Set the bitmap bits */
 +    if (!SURFACE_bSetBitmapBits(psurf, fjBitmap, cjWidthBytes, pvBits))
 +    {
 +        /* Bail out if that failed */
 +        DPRINT1("SURFACE_bSetBitmapBits failed.\n");
 +        SURFACE_FreeSurfaceByHandle(hbmp);
 +        return NULL;
 +    }
 +
 +    /* Unlock the surface and return */
 +    SURFACE_UnlockSurface(psurf);
 +    return hbmp;
 +}
 +
 +/* Creates a DDB surface,
 + * as in CreateCompatibleBitmap or CreateBitmap.
 + */
 +HBITMAP
 +APIENTRY
 +GreCreateBitmap(
 +    IN INT nWidth,
 +    IN INT nHeight,
 +    IN UINT cPlanes,
 +    IN UINT cBitsPixel,
 +    IN OPTIONAL PVOID pvBits)
 +{
 +    /* Call the extended function */
 +    return GreCreateBitmapEx(nWidth,
 +                             nHeight,
 +                             0, /* auto width */
 +                             BitmapFormat(cBitsPixel * cPlanes, BI_RGB),
 +                             0, /* no bitmap flags */
 +                             0, /* auto size */
 +                             pvBits,
 +                                                       DDB_SURFACE /* DDB */);
 +}
 +
 +HBITMAP
 +APIENTRY
 +NtGdiCreateBitmap(
 +    IN INT nWidth,
 +    IN INT nHeight,
 +    IN UINT cPlanes,
 +    IN UINT cBitsPixel,
 +    IN OPTIONAL LPBYTE pUnsafeBits)
 +{
 +    HBITMAP hbmp;
 +    ULONG cjWidthBytes, iFormat;
 +
 +    /* NOTE: Windows also doesn't store nr. of planes separately! */
 +    cBitsPixel = BITMAP_GetRealBitsPixel(cBitsPixel * cPlanes);
 +
 +    /* Calculate bitmap format */
 +    iFormat = BitmapFormat(cBitsPixel, BI_RGB);
 +
 +    /* Check parameters */
 +    if (iFormat == 0 || nWidth <= 0 || nWidth >= 0x8000000 || nHeight <= 0)
 +    {
 +        DPRINT1("Width = %d, Height = %d BitsPixel = %d\n",
 +                nWidth, nHeight, cBitsPixel);
 +        EngSetLastError(ERROR_INVALID_PARAMETER);
 +        return NULL;
 +    }
 +
 +    /* Make sure that cjBits will not overflow */
 +    cjWidthBytes = BITMAP_GetWidthBytes(nWidth, cBitsPixel);
 +    if ((ULONGLONG)cjWidthBytes * nHeight >= 0x100000000ULL)
 +    {
 +        DPRINT1("Width = %d, Height = %d BitsPixel = %d\n",
 +                nWidth, nHeight, cBitsPixel);
 +        EngSetLastError(ERROR_INVALID_PARAMETER);
 +        return NULL;
 +    }
 +
 +      /* cBitsPixel = cBitsPixel * cPlanes now! */
 +      hbmp = GreCreateBitmap(nWidth, nHeight, 1, cBitsPixel, NULL);
 +
 +    if (pUnsafeBits)
 +    {
 +              PSURFACE psurf = SURFACE_LockSurface(hbmp);
 +        _SEH2_TRY
 +        {
 +            ProbeForRead(pUnsafeBits, cjWidthBytes * nHeight, 1);
 +            UnsafeSetBitmapBits(psurf, 0, pUnsafeBits);
 +        }
 +        _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
 +        {
 +                      SURFACE_UnlockSurface(psurf);
 +            SURFACE_FreeSurfaceByHandle(hbmp);
 +            _SEH2_YIELD(return NULL;)
 +        }
 +        _SEH2_END
 +
 +              SURFACE_UnlockSurface(psurf);
 +    }
 +
 +    return hbmp;
 +}
 +
 +
 +HBITMAP FASTCALL
 +IntCreateCompatibleBitmap(
 +    PDC Dc,
 +    INT Width,
 +    INT Height)
 +{
 +    HBITMAP Bmp = NULL;
 +
 +    /* MS doc says if width or height is 0, return 1-by-1 pixel, monochrome bitmap */
 +    if (0 == Width || 0 == Height)
 +    {
 +        Bmp = NtGdiGetStockObject(DEFAULT_BITMAP);
 +    }
 +    else
 +    {
 +        if (Dc->dctype != DC_TYPE_MEMORY)
 +        {
 +            PSURFACE psurf;
 +            SIZEL size;
 +
 +            size.cx = abs(Width);
 +            size.cy = abs(Height);
 +            Bmp = GreCreateBitmap(abs(Width),
 +                                  abs(Height),
 +                                  1,
 +                                  Dc->ppdev->gdiinfo.cBitsPixel,
 +                                  NULL);
 +            psurf = SURFACE_LockSurface(Bmp);
 +            ASSERT(psurf);
 +            /* Set palette */
 +            psurf->ppal = PALETTE_ShareLockPalette(Dc->ppdev->devinfo.hpalDefault);
 +            /* Set flags */
 +            psurf->flags = API_BITMAP;
 +            psurf->hdc = NULL; // Fixme
 +            SURFACE_UnlockSurface(psurf);
 +        }
 +        else
 +        {
 +            DIBSECTION dibs;
 +            INT Count;
 +            PSURFACE psurf = Dc->dclevel.pSurface;
 +            Count = BITMAP_GetObject(psurf, sizeof(dibs), &dibs);
 +
 +            if (Count)
 +            {
 +                if (Count == sizeof(BITMAP))
 +                {
 +                    SIZEL size;
 +                    PSURFACE psurfBmp;
 +                    size.cx = abs(Width);
 +                    size.cy = abs(Height);
 +                                      Bmp = GreCreateBitmap(abs(Width),
 +                                  abs(Height),
 +                                  1,
 +                                  dibs.dsBm.bmBitsPixel,
 +                                  NULL);
 +                    psurfBmp = SURFACE_LockSurface(Bmp);
 +                    ASSERT(psurfBmp);
 +                    /* Assign palette */
 +                    psurfBmp->ppal = psurf->ppal;
 +                    GDIOBJ_IncrementShareCount((POBJ)psurf->ppal);
 +                    /* Set flags */
 +                    psurfBmp->flags = API_BITMAP;
 +                    psurfBmp->hdc = NULL; // Fixme
 +                    SURFACE_UnlockSurface(psurfBmp);
 +                }
 +                else
 +                {
 +                    /* A DIB section is selected in the DC */
 +                                      BYTE buf[sizeof(BITMAPINFOHEADER) + 256*sizeof(RGBQUAD)] = {0};
 +                    PVOID Bits;
 +                                      BITMAPINFO* bi = (BITMAPINFO*)buf;
 +
 +                    bi->bmiHeader.biSize          = sizeof(bi->bmiHeader);
 +                    bi->bmiHeader.biWidth         = Width;
 +                    bi->bmiHeader.biHeight        = Height;
 +                    bi->bmiHeader.biPlanes        = dibs.dsBmih.biPlanes;
 +                    bi->bmiHeader.biBitCount      = dibs.dsBmih.biBitCount;
 +                    bi->bmiHeader.biCompression   = dibs.dsBmih.biCompression;
 +                    bi->bmiHeader.biSizeImage     = 0;
 +                    bi->bmiHeader.biXPelsPerMeter = dibs.dsBmih.biXPelsPerMeter;
 +                    bi->bmiHeader.biYPelsPerMeter = dibs.dsBmih.biYPelsPerMeter;
 +                    bi->bmiHeader.biClrUsed       = dibs.dsBmih.biClrUsed;
 +                    bi->bmiHeader.biClrImportant  = dibs.dsBmih.biClrImportant;
 +
 +                    if (bi->bmiHeader.biCompression == BI_BITFIELDS)
 +                    {
 +                        /* Copy the color masks */
 +                        RtlCopyMemory(bi->bmiColors, dibs.dsBitfields, 3*sizeof(RGBQUAD));
 +                    }
 +                    else if (bi->bmiHeader.biBitCount <= 8)
 +                    {
 +                        /* Copy the color table */
 +                        UINT Index;
 +                        PPALETTE PalGDI;
 +
 +                        if (!psurf->ppal)
 +                        {
 +                            SetLastWin32Error(ERROR_INVALID_HANDLE);
 +                            return 0;
 +                        }
 +
 +                        PalGDI = PALETTE_LockPalette(psurf->ppal->BaseObject.hHmgr);
 +
 +                        for (Index = 0;
 +                                Index < 256 && Index < PalGDI->NumColors;
 +                                Index++)
 +                        {
 +                            bi->bmiColors[Index].rgbRed   = PalGDI->IndexedColors[Index].peRed;
 +                            bi->bmiColors[Index].rgbGreen = PalGDI->IndexedColors[Index].peGreen;
 +                            bi->bmiColors[Index].rgbBlue  = PalGDI->IndexedColors[Index].peBlue;
 +                            bi->bmiColors[Index].rgbReserved = 0;
 +                        }
 +                        PALETTE_UnlockPalette(PalGDI);
 +
 +                        Bmp = DIB_CreateDIBSection(Dc,
 +                                                   bi,
 +                                                   DIB_RGB_COLORS,
 +                                                   &Bits,
 +                                                   NULL,
 +                                                   0,
 +                                                   0);
 +                        return Bmp;
 +                    }
 +                }
 +            }
 +        }
 +    }
 +    return Bmp;
 +}
 +
 +HBITMAP APIENTRY
 +NtGdiCreateCompatibleBitmap(
 +    HDC hDC,
 +    INT Width,
 +    INT Height)
 +{
 +    HBITMAP Bmp;
 +    PDC Dc;
 +
 +    if (Width <= 0 || Height <= 0 || (Width * Height) > 0x3FFFFFFF)
 +    {
 +        SetLastWin32Error(ERROR_INVALID_PARAMETER);
 +        return NULL;
 +    }
 +
 +    if (!hDC)
 +        return GreCreateBitmap(Width, Height, 1, 1, 0);
 +
 +    Dc = DC_LockDc(hDC);
 +
 +    DPRINT("NtGdiCreateCompatibleBitmap(%04x,%d,%d, bpp:%d) = \n",
 +           hDC, Width, Height, Dc->ppdev->gdiinfo.cBitsPixel);
 +
 +    if (NULL == Dc)
 +    {
 +        SetLastWin32Error(ERROR_INVALID_HANDLE);
 +        return NULL;
 +    }
 +
 +    Bmp = IntCreateCompatibleBitmap(Dc, Width, Height);
 +
 +    DPRINT("\t\t%04x\n", Bmp);
 +    DC_UnlockDc(Dc);
 +    return Bmp;
 +}
 +
 +BOOL APIENTRY
 +NtGdiGetBitmapDimension(
 +    HBITMAP hBitmap,
 +    LPSIZE Dimension)
 +{
 +    PSURFACE psurfBmp;
 +    BOOL Ret = TRUE;
 +
 +    if (hBitmap == NULL)
 +        return FALSE;
 +
 +    psurfBmp = SURFACE_LockSurface(hBitmap);
 +    if (psurfBmp == NULL)
 +    {
 +        SetLastWin32Error(ERROR_INVALID_HANDLE);
 +        return FALSE;
 +    }
 +
 +    _SEH2_TRY
 +    {
 +        ProbeForWrite(Dimension, sizeof(SIZE), 1);
 +        *Dimension = psurfBmp->sizlDim;
 +    }
 +    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
 +    {
 +        Ret = FALSE;
 +    }
 +    _SEH2_END
 +
 +    SURFACE_UnlockSurface(psurfBmp);
 +
 +    return Ret;
 +}
 +
 +COLORREF APIENTRY
 +NtGdiGetPixel(HDC hDC, INT XPos, INT YPos)
 +{
 +    PDC dc = NULL;
 +    COLORREF Result = (COLORREF)CLR_INVALID; // default to failure
 +    BOOL bInRect = FALSE;
 +    SURFACE *psurf;
 +    SURFOBJ *pso;
 +    PPALETTE ppal;
 +    EXLATEOBJ exlo;
 +    HBITMAP hBmpTmp;
 +
 +    dc = DC_LockDc(hDC);
 +
 +    if (!dc)
 +    {
 +        SetLastWin32Error(ERROR_INVALID_HANDLE);
 +        return Result;
 +    }
 +
 +    if (dc->dctype == DC_TYPE_INFO)
 +    {
 +        DC_UnlockDc(dc);
 +        return Result;
 +    }
 +
 +    XPos += dc->ptlDCOrig.x;
 +    YPos += dc->ptlDCOrig.y;
 +    if (RECTL_bPointInRect(&dc->rosdc.CombinedClip->rclBounds, XPos, YPos))
 +    {
 +        bInRect = TRUE;
 +        psurf = dc->dclevel.pSurface;
 +        if (psurf)
 +        {
 +            pso = &psurf->SurfObj;
 +            if (psurf->ppal)
 +            {
 +                ppal = psurf->ppal;
 +                GDIOBJ_IncrementShareCount(&ppal->BaseObject);
 +            }
 +            else
 +                ppal = PALETTE_ShareLockPalette(dc->ppdev->devinfo.hpalDefault);
 +
 +            if (psurf->SurfObj.iBitmapFormat == BMF_1BPP && !psurf->hSecure)
 +            {
 +                /* FIXME: palette should be gpalMono already ! */
 +                EXLATEOBJ_vInitialize(&exlo, &gpalMono, &gpalRGB, 0, 0xffffff, 0);
 +            }
 +            else
 +            {
 +                EXLATEOBJ_vInitialize(&exlo, ppal, &gpalRGB, 0, 0xffffff, 0);
 +            }
 +
 +            // check if this DC has a DIB behind it...
 +            if (pso->pvScan0) // STYPE_BITMAP == pso->iType
 +            {
 +                ASSERT(pso->lDelta);
 +                Result = XLATEOBJ_iXlate(&exlo.xlo,
 +                                         DibFunctionsForBitmapFormat[pso->iBitmapFormat].DIB_GetPixel(pso, XPos, YPos));
 +            }
 +
 +            EXLATEOBJ_vCleanup(&exlo);
 +            PALETTE_ShareUnlockPalette(ppal);
 +        }
 +    }
 +    DC_UnlockDc(dc);
 +
 +    // if Result is still CLR_INVALID, then the "quick" method above didn't work
 +    if (bInRect && Result == CLR_INVALID)
 +    {
 +        // FIXME: create a 1x1 32BPP DIB, and blit to it
 +        HDC hDCTmp = NtGdiCreateCompatibleDC(hDC);
 +        if (hDCTmp)
 +        {
 +            static const BITMAPINFOHEADER bih = { sizeof(BITMAPINFOHEADER), 1, 1, 1, 32, BI_RGB, 0, 0, 0, 0, 0 };
 +            BITMAPINFO bi;
 +            RtlMoveMemory(&(bi.bmiHeader), &bih, sizeof(bih));
 +            hBmpTmp = NtGdiCreateDIBitmapInternal(hDC,
 +                                                  bi.bmiHeader.biWidth,
 +                                                  bi.bmiHeader.biHeight,
 +                                                  0,
 +                                                  NULL,
 +                                                  &bi,
 +                                                  DIB_RGB_COLORS,
 +                                                  bi.bmiHeader.biBitCount,
 +                                                  bi.bmiHeader.biSizeImage,
 +                                                  0,
 +                                                  0);
 +
 +            //HBITMAP hBmpTmp = GreCreateBitmap(1, 1, 1, 32, NULL);
 +            if (hBmpTmp)
 +            {
 +                HBITMAP hBmpOld = (HBITMAP)NtGdiSelectBitmap(hDCTmp, hBmpTmp);
 +                if (hBmpOld)
 +                {
 +                    PSURFACE psurf;
 +
 +                    NtGdiBitBlt(hDCTmp, 0, 0, 1, 1, hDC, XPos, YPos, SRCCOPY, 0, 0);
 +                    NtGdiSelectBitmap(hDCTmp, hBmpOld);
 +
 +                    // our bitmap is no longer selected, so we can access it's stuff...
 +                    psurf = SURFACE_LockSurface(hBmpTmp);
 +                    if (psurf)
 +                    {
 +                        // Dont you need to convert something here?
 +                        Result = *(COLORREF*)psurf->SurfObj.pvScan0;
 +                        SURFACE_UnlockSurface(psurf);
 +                    }
 +                }
 +                GreDeleteObject(hBmpTmp);
 +            }
 +            NtGdiDeleteObjectApp(hDCTmp);
 +        }
 +    }
 +
 +    return Result;
 +}
 +
 +
 +LONG APIENTRY
 +IntGetBitmapBits(
 +    PSURFACE psurf,
 +    DWORD Bytes,
 +    OUT PBYTE Bits)
 +{
 +    LONG ret;
 +
 +    ASSERT(Bits);
 +
 +    /* Don't copy more bytes than the buffer has */
 +    Bytes = min(Bytes, psurf->SurfObj.cjBits);
 +
 +#if 0
 +    /* FIXME: Call DDI CopyBits here if available  */
 +    if (psurf->DDBitmap)
 +    {
 +        DPRINT("Calling device specific BitmapBits\n");
 +        if (psurf->DDBitmap->funcs->pBitmapBits)
 +        {
 +            ret = psurf->DDBitmap->funcs->pBitmapBits(hbitmap,
 +                                                      bits,
 +                                                      count,
 +                                                      DDB_GET);
 +        }
 +        else
 +        {
 +            ERR_(bitmap)("BitmapBits == NULL??\n");
 +            ret = 0;
 +        }
 +    }
 +    else
 +#endif
 +    {
 +        RtlCopyMemory(Bits, psurf->SurfObj.pvBits, Bytes);
 +        ret = Bytes;
 +    }
 +    return ret;
 +}
 +
 +VOID
 +FASTCALL
 +UnsafeGetBitmapBits(
 +    PSURFACE psurf,
 +      DWORD Bytes,
 +      OUT PBYTE pvBits)
 +{
 +      PUCHAR pjDst, pjSrc;
 +    LONG lDeltaDst, lDeltaSrc;
 +    ULONG nWidth, nHeight, cBitsPixel;
 +
 +    nWidth = psurf->SurfObj.sizlBitmap.cx;
 +    nHeight = psurf->SurfObj.sizlBitmap.cy;
 +    cBitsPixel = BitsPerFormat(psurf->SurfObj.iBitmapFormat);
 +
 +    /* Get pointers */
 +    pjSrc = psurf->SurfObj.pvScan0;
 +    pjDst = pvBits;
 +    lDeltaSrc = psurf->SurfObj.lDelta;
 +    lDeltaDst = BITMAP_GetWidthBytes(nWidth, cBitsPixel);
 +
 +    while (nHeight--)
 +    {
 +        /* Copy one line */
 +        RtlCopyMemory(pjDst, pjSrc, lDeltaDst);
 +        pjSrc += lDeltaSrc;
 +        pjDst += lDeltaDst;
 +    }
 +}
 +
 +LONG APIENTRY
 +NtGdiGetBitmapBits(
 +    HBITMAP hBitmap,
 +    ULONG Bytes,
 +    OUT OPTIONAL PBYTE pUnsafeBits)
 +{
 +    PSURFACE psurf;
 +    LONG bmSize, ret;
 +
 +    if (pUnsafeBits != NULL && Bytes == 0)
 +    {
 +        return 0;
 +    }
 +
 +    psurf = SURFACE_LockSurface(hBitmap);
 +    if (!psurf)
 +    {
 +        SetLastWin32Error(ERROR_INVALID_HANDLE);
 +        return 0;
 +    }
 +
 +    bmSize = BITMAP_GetWidthBytes(psurf->SurfObj.sizlBitmap.cx,
 +             BitsPerFormat(psurf->SurfObj.iBitmapFormat)) *
 +             abs(psurf->SurfObj.sizlBitmap.cy);
 +
 +    /* If the bits vector is null, the function should return the read size */
 +    if (pUnsafeBits == NULL)
 +    {
 +        SURFACE_UnlockSurface(psurf);
 +        return bmSize;
 +    }
 +
 +    /* Don't copy more bytes than the buffer has */
 +    Bytes = min(Bytes, bmSize);
 +
 +    // FIXME: use MmSecureVirtualMemory
 +    _SEH2_TRY
 +    {
 +        ProbeForWrite(pUnsafeBits, Bytes, 1);
 +        UnsafeGetBitmapBits(psurf, Bytes, pUnsafeBits);
 +              ret = Bytes;
 +    }
 +    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
 +    {
 +        ret = 0;
 +    }
 +    _SEH2_END
 +
 +    SURFACE_UnlockSurface(psurf);
 +
 +    return ret;
 +}
 +
 +
 +LONG APIENTRY
 +NtGdiSetBitmapBits(
 +    HBITMAP hBitmap,
 +    DWORD Bytes,
 +    IN PBYTE pUnsafeBits)
 +{
 +    LONG ret;
 +    PSURFACE psurf;
 +
 +    if (pUnsafeBits == NULL || Bytes == 0)
 +    {
 +        return 0;
 +    }
 +
 +    psurf = SURFACE_LockSurface(hBitmap);
 +    if (psurf == NULL)
 +    {
 +        SetLastWin32Error(ERROR_INVALID_HANDLE);
 +        return 0;
 +    }
 +
 +    _SEH2_TRY
 +    {
 +        ProbeForRead(pUnsafeBits, Bytes, 1);
 +        UnsafeSetBitmapBits(psurf, Bytes, pUnsafeBits);
 +        ret = 1;
 +    }
 +    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
 +    {
 +        ret = 0;
 +    }
 +    _SEH2_END
 +
 +    SURFACE_UnlockSurface(psurf);
 +
 +    return ret;
 +}
 +
 +BOOL APIENTRY
 +NtGdiSetBitmapDimension(
 +    HBITMAP hBitmap,
 +    INT Width,
 +    INT Height,
 +    LPSIZE Size)
 +{
 +    PSURFACE psurf;
 +    BOOL Ret = TRUE;
 +
 +    if (hBitmap == NULL)
 +        return FALSE;
 +
 +    psurf = SURFACE_LockSurface(hBitmap);
 +    if (psurf == NULL)
 +    {
 +        SetLastWin32Error(ERROR_INVALID_HANDLE);
 +        return FALSE;
 +    }
 +
 +    if (Size)
 +    {
 +        _SEH2_TRY
 +        {
 +            ProbeForWrite(Size, sizeof(SIZE), 1);
 +            *Size = psurf->sizlDim;
 +        }
 +        _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
 +        {
 +            Ret = FALSE;
 +        }
 +        _SEH2_END
 +    }
 +
 +    /* The dimension is changed even if writing the old value failed */
 +    psurf->sizlDim.cx = Width;
 +    psurf->sizlDim.cy = Height;
 +
 +    SURFACE_UnlockSurface(psurf);
 +
 +    return Ret;
 +}
 +
 +VOID IntHandleSpecialColorType(HDC hDC, COLORREF* Color)
 +{
 +    PDC pdc = NULL;
 +    RGBQUAD quad;
 +    PALETTEENTRY palEntry;
 +    UINT index;
 +
 +    switch (*Color >> 24)
 +    {
 +        case 0x10: /* DIBINDEX */
 +            if (IntGetDIBColorTable(hDC, LOWORD(*Color), 1, &quad) == 1)
 +            {
 +                *Color = RGB(quad.rgbRed, quad.rgbGreen, quad.rgbBlue);
 +            }
 +            else
 +            {
 +                /* Out of color table bounds - use black */
 +                *Color = RGB(0, 0, 0);
 +            }
 +            break;
 +        case 0x02: /* PALETTERGB */
 +            pdc = DC_LockDc(hDC);
 +            if (pdc->dclevel.hpal != NtGdiGetStockObject(DEFAULT_PALETTE))
 +            {
 +                index = NtGdiGetNearestPaletteIndex(pdc->dclevel.hpal, *Color);
 +                IntGetPaletteEntries(pdc->dclevel.hpal, index, 1, &palEntry);
 +                *Color = RGB(palEntry.peRed, palEntry.peGreen, palEntry.peBlue);
 +            }
 +            else
 +            {
 +                /* Use the pure color */
 +                *Color = *Color & 0x00FFFFFF;
 +            }
 +            DC_UnlockDc(pdc);
 +            break;
 +        case 0x01: /* PALETTEINDEX */
 +            pdc = DC_LockDc(hDC);
 +            if (IntGetPaletteEntries(pdc->dclevel.hpal, LOWORD(*Color), 1, &palEntry) == 1)
 +            {
 +                *Color = RGB(palEntry.peRed, palEntry.peGreen, palEntry.peBlue);
 +            }
 +            else
 +            {
 +                /* Index does not exist, use zero index */
 +                IntGetPaletteEntries(pdc->dclevel.hpal, 0, 1, &palEntry);
 +                *Color = RGB(palEntry.peRed, palEntry.peGreen, palEntry.peBlue);
 +            }
 +            DC_UnlockDc(pdc);
 +            break;
 +        default:
 +            DPRINT("Unsupported color type %d passed\n", *Color >> 24);
 +            break;
 +    }
 +}
 +
 +BOOL APIENTRY
 +GdiSetPixelV(
 +    HDC hDC,
 +    INT X,
 +    INT Y,
 +    COLORREF Color)
 +{
 +    HBRUSH hBrush;
 +    HGDIOBJ OldBrush;
 +
 +    if ((Color & 0xFF000000) != 0)
 +    {
 +        IntHandleSpecialColorType(hDC, &Color);
 +    }
 +
 +    hBrush = NtGdiCreateSolidBrush(Color, NULL);
 +    if (hBrush == NULL)
 +        return FALSE;
 +
 +    OldBrush = NtGdiSelectBrush(hDC, hBrush);
 +    if (OldBrush == NULL)
 +    {
 +        GreDeleteObject(hBrush);
 +        return FALSE;
 +    }
 +
 +    NtGdiPatBlt(hDC, X, Y, 1, 1, PATCOPY);
 +    NtGdiSelectBrush(hDC, OldBrush);
 +    GreDeleteObject(hBrush);
 +
 +    return TRUE;
 +}
 +
 +COLORREF APIENTRY
 +NtGdiSetPixel(
 +    HDC hDC,
 +    INT X,
 +    INT Y,
 +    COLORREF Color)
 +{
 +    DPRINT("0 NtGdiSetPixel X %ld Y %ld C %ld\n", X, Y, Color);
 +
 +    if (GdiSetPixelV(hDC,X,Y,Color))
 +    {
 +        Color = NtGdiGetPixel(hDC,X,Y);
 +        DPRINT("1 NtGdiSetPixel X %ld Y %ld C %ld\n", X, Y, Color);
 +        return Color;
 +    }
 +
 +    Color = (COLORREF)CLR_INVALID;
 +    DPRINT("2 NtGdiSetPixel X %ld Y %ld C %ld\n", X, Y, Color);
 +    return Color;
 +}
 +
 +
 +/*  Internal Functions  */
 +
 +UINT FASTCALL
 +BITMAP_GetRealBitsPixel(UINT nBitsPixel)
 +{
 +    if (nBitsPixel <= 1)
 +        return 1;
 +    if (nBitsPixel <= 4)
 +        return 4;
 +    if (nBitsPixel <= 8)
 +        return 8;
 +    if (nBitsPixel <= 16)
 +        return 16;
 +    if (nBitsPixel <= 24)
 +        return 24;
 +    if (nBitsPixel <= 32)
 +        return 32;
 +
 +    return 0;
 +}
 +
 +INT FASTCALL
 +BITMAP_GetWidthBytes(INT bmWidth, INT bpp)
 +{
 +#if 0
 +    switch (bpp)
 +    {
 +    case 1:
 +        return 2 * ((bmWidth+15) >> 4);
 +
 +    case 24:
 +        bmWidth *= 3; /* fall through */
 +    case 8:
 +        return bmWidth + (bmWidth & 1);
 +
 +    case 32:
 +        return bmWidth * 4;
 +
 +    case 16:
 +    case 15:
 +        return bmWidth * 2;
 +
 +    case 4:
 +        return 2 * ((bmWidth+3) >> 2);
 +
 +    default:
 +        DPRINT ("stub");
 +    }
 +
 +    return -1;
 +#endif
 +
 +    return ((bmWidth * bpp + 15) & ~15) >> 3;
 +}
 +
 +HBITMAP FASTCALL
 +BITMAP_CopyBitmap(HBITMAP hBitmap)
 +{
 +    HBITMAP res;
 +    BITMAP bm;
 +    SURFACE *Bitmap, *resBitmap;
 +    SIZEL Size;
 +
 +    if (hBitmap == NULL)
 +    {
 +        return 0;
 +    }
 +
 +    Bitmap = SURFACE_LockSurface(hBitmap);
 +    if (Bitmap == NULL)
 +    {
 +        return 0;
 +    }
 +
 +    BITMAP_GetObject(Bitmap, sizeof(BITMAP), (PVOID)&bm);
 +    bm.bmBits = NULL;
 +    if (Bitmap->SurfObj.lDelta >= 0)
 +        bm.bmHeight = -bm.bmHeight;
 +
 +    Size.cx = abs(bm.bmWidth);
 +    Size.cy = abs(bm.bmHeight);
 +    res = GreCreateBitmapEx(Size.cx,
 +                                                      Size.cy,
 +                                                      bm.bmWidthBytes,
 +                                                      Bitmap->SurfObj.iBitmapFormat,
 +                                                      Bitmap->SurfObj.fjBitmap,
 +                                                      Bitmap->SurfObj.cjBits,
 +                                                      NULL,
 +                                                      Bitmap->flags);
 +
 +
 +    if (res)
 +    {
 +        resBitmap = SURFACE_LockSurface(res);
 +        if (resBitmap)
 +        {
 +            IntSetBitmapBits(resBitmap, Bitmap->SurfObj.cjBits, Bitmap->SurfObj.pvBits);
++            resBitmap->ppal = Bitmap->ppal;
++            GDIOBJ_IncrementShareCount((POBJ)Bitmap->ppal);
 +                      SURFACE_UnlockSurface(resBitmap);
 +        }
 +        else
 +        {
 +            GreDeleteObject(res);
 +            res = NULL;
 +        }
 +    }
 +
 +    SURFACE_UnlockSurface(Bitmap);
 +
 +    return  res;
 +}
 +
 +INT APIENTRY
 +BITMAP_GetObject(SURFACE *psurf, INT Count, LPVOID buffer)
 +{
 +    PBITMAP pBitmap;
 +
 +    if (!buffer) return sizeof(BITMAP);
 +    if ((UINT)Count < sizeof(BITMAP)) return 0;
 +
 +    /* always fill a basic BITMAP structure */
 +    pBitmap = buffer;
 +    pBitmap->bmType = 0;
 +    pBitmap->bmWidth = psurf->SurfObj.sizlBitmap.cx;
 +    pBitmap->bmHeight = psurf->SurfObj.sizlBitmap.cy;
 +    pBitmap->bmPlanes = 1;
 +    pBitmap->bmBitsPixel = BitsPerFormat(psurf->SurfObj.iBitmapFormat);
 +      pBitmap->bmWidthBytes = BITMAP_GetWidthBytes(pBitmap->bmWidth, pBitmap->bmBitsPixel);
 +
 +    /* Check for DIB section */
 +    if (psurf->hSecure)
 +    {
 +        /* Set bmBits in this case */
 +        pBitmap->bmBits = psurf->SurfObj.pvBits;
 +              /* DIBs data are 32 bits aligned */
 +              pBitmap->bmWidthBytes = DIB_GetDIBWidthBytes(pBitmap->bmWidth, pBitmap->bmBitsPixel);
 +
 +        if (Count >= sizeof(DIBSECTION))
 +        {
 +            /* Fill rest of DIBSECTION */
 +            PDIBSECTION pds = buffer;
 +
 +            pds->dsBmih.biSize = sizeof(BITMAPINFOHEADER);
 +            pds->dsBmih.biWidth = pds->dsBm.bmWidth;
 +            pds->dsBmih.biHeight = pds->dsBm.bmHeight;
 +            pds->dsBmih.biPlanes = pds->dsBm.bmPlanes;
 +            pds->dsBmih.biBitCount = pds->dsBm.bmBitsPixel;
 +                      if(psurf->ppal->Mode & PAL_BITFIELDS)
 +                      {
 +                              pds->dsBmih.biCompression = BI_BITFIELDS;
 +                      }
 +                      else
 +                      {
 +                              switch (psurf->SurfObj.iBitmapFormat)
 +                              {
 +                                      case BMF_1BPP:
 +                                      case BMF_4BPP:
 +                                      case BMF_8BPP:
 +                                      case BMF_16BPP:
 +                                      case BMF_24BPP:
 +                                      case BMF_32BPP:
 +                                         pds->dsBmih.biCompression = BI_RGB;
 +                                         break;
 +                                      case BMF_4RLE:
 +                                         pds->dsBmih.biCompression = BI_RLE4;
 +                                         break;
 +                                      case BMF_8RLE:
 +                                         pds->dsBmih.biCompression = BI_RLE8;
 +                                         break;
 +                                      case BMF_JPEG:
 +                                         pds->dsBmih.biCompression = BI_JPEG;
 +                                         break;
 +                                      case BMF_PNG:
 +                                         pds->dsBmih.biCompression = BI_PNG;
 +                                         break;
 +                              }
 +                      }
 +            pds->dsBmih.biSizeImage = psurf->SurfObj.cjBits;
 +            pds->dsBmih.biXPelsPerMeter = 0;
 +            pds->dsBmih.biYPelsPerMeter = 0;
 +            pds->dsBmih.biClrUsed = psurf->ppal->NumColors;
 +            pds->dsBmih.biClrImportant = psurf->biClrImportant;
 +            pds->dsBitfields[0] = psurf->ppal->RedMask;
 +            pds->dsBitfields[1] = psurf->ppal->GreenMask;
 +            pds->dsBitfields[2] = psurf->ppal->BlueMask;
 +            pds->dshSection = psurf->hDIBSection;
 +            pds->dsOffset = psurf->dwOffset;
 +
 +            return sizeof(DIBSECTION);
 +        }
 +    }
 +    else
 +    {
 +        /* not set according to wine test, confirmed in win2k */
 +        pBitmap->bmBits = NULL;
 +    }
 +
 +    return sizeof(BITMAP);
 +}
 +
 +/*
 + * @implemented
 + */
 +HDC
 +APIENTRY
 +NtGdiGetDCforBitmap(
 +    IN HBITMAP hsurf)
 +{
 +    HDC hdc = NULL;
 +    PSURFACE psurf = SURFACE_LockSurface(hsurf);
 +    if (psurf)
 +    {
 +        hdc = psurf->hdc;
 +        SURFACE_UnlockSurface(psurf);
 +    }
 +    return hdc;
 +}
 +
 +
 +/* EOF */