Пример #1
0
PPALETTE
NTAPI
PALETTE_AllocPalette2(ULONG Mode,
                     ULONG NumColors,
                     ULONG *Colors,
                     ULONG Red,
                     ULONG Green,
                     ULONG Blue)
{
    PPALETTE PalGDI;

    PalGDI = (PPALETTE)GDIOBJ_AllocateObject(GDIObjType_PAL_TYPE,
                                             sizeof(PALETTE),
                                             BASEFLAG_LOOKASIDE);
    if (!PalGDI)
    {
        DPRINT1("Could not allocate a palette.\n");
        return NULL;
    }

    PalGDI->Self = PalGDI->BaseObject.hHmgr;
    PalGDI->flFlags = Mode;

    if (NULL != Colors)
    {
        PalGDI->IndexedColors = ExAllocatePoolWithTag(PagedPool,
                                                      sizeof(PALETTEENTRY) * NumColors,
                                                      TAG_PALETTE);
        if (NULL == PalGDI->IndexedColors)
        {
            GDIOBJ_vDeleteObject(&PalGDI->BaseObject);
            return NULL;
        }
        RtlCopyMemory(PalGDI->IndexedColors, Colors, sizeof(PALETTEENTRY) * NumColors);
    }

    if (Mode & PAL_INDEXED)
    {
        PalGDI->NumColors = NumColors;
    }
    else if (Mode & PAL_BITFIELDS)
    {
        PalGDI->RedMask = Red;
        PalGDI->GreenMask = Green;
        PalGDI->BlueMask = Blue;

        if (Red == 0x7c00 && Green == 0x3E0 && Blue == 0x1F)
            PalGDI->flFlags |= PAL_RGB16_555;
        else if (Red == 0xF800 && Green == 0x7E0 && Blue == 0x1F)
            PalGDI->flFlags |= PAL_RGB16_565;
        else if (Red == 0xFF0000 && Green == 0xFF00 && Blue == 0xFF)
            PalGDI->flFlags |= PAL_BGR;
        else if (Red == 0xFF && Green == 0xFF00 && Blue == 0xFF0000)
            PalGDI->flFlags |= PAL_RGB;
    }

    return PalGDI;
}
Пример #2
0
HPALETTE
FASTCALL
PALETTE_AllocPaletteIndexedRGB(ULONG NumColors,
                               CONST RGBQUAD *Colors)
{
    HPALETTE NewPalette;
    PPALETTE PalGDI;
    UINT i;

    PalGDI = (PPALETTE)GDIOBJ_AllocateObject(GDIObjType_PAL_TYPE,
                                           sizeof(PALETTE),
                                           BASEFLAG_LOOKASIDE);
    if (!PalGDI)
    {
        DPRINT1("Could not allocate a palette.\n");
        return NULL;
    }

    if (!GDIOBJ_hInsertObject(&PalGDI->BaseObject, GDI_OBJ_HMGR_POWNED))
    {
        DPRINT1("Could not insert palette into handle table.\n");
        GDIOBJ_vFreeObject(&PalGDI->BaseObject);
        return NULL;
    }

    NewPalette = PalGDI->BaseObject.hHmgr;

    PalGDI->Self = NewPalette;
    PalGDI->flFlags = PAL_INDEXED;

    PalGDI->IndexedColors = ExAllocatePoolWithTag(PagedPool,
                                                  sizeof(PALETTEENTRY) * NumColors,
                                                  TAG_PALETTE);
    if (NULL == PalGDI->IndexedColors)
    {
        GDIOBJ_vDeleteObject(&PalGDI->BaseObject);
        return NULL;
    }

    for (i = 0; i < NumColors; i++)
    {
        PalGDI->IndexedColors[i].peRed = Colors[i].rgbRed;
        PalGDI->IndexedColors[i].peGreen = Colors[i].rgbGreen;
        PalGDI->IndexedColors[i].peBlue = Colors[i].rgbBlue;
        PalGDI->IndexedColors[i].peFlags = 0;
    }

    PalGDI->NumColors = NumColors;

    PALETTE_UnlockPalette(PalGDI);

    return NewPalette;
}
Пример #3
0
/*
 * @implemented
 */
BOOL
APIENTRY
EngDeletePalette(IN HPALETTE hpal)
{
    PPALETTE ppal;

    ppal = PALETTE_ShareLockPalette(hpal);
    if (!ppal) return FALSE;

    GDIOBJ_vDeleteObject(&ppal->BaseObject);

    return TRUE;
}
Пример #4
0
BOOL
APIENTRY
EngDeleteSurface(
    _In_ _Post_ptr_invalid_ HSURF hsurf)
{
    PSURFACE psurf;

    psurf = SURFACE_ShareLockSurface(hsurf);
    if (!psurf)
    {
        DPRINT1("Could not reference surface %p to delete\n", hsurf);
        return FALSE;
    }

    GDIOBJ_vDeleteObject(&psurf->BaseObject);
    return TRUE;
}
Пример #5
0
/*
 * @implemented
 */
HPALETTE
APIENTRY
NtGdiCreatePaletteInternal(
    IN LPLOGPALETTE plogpalUser,
    IN UINT cEntries)
{
    HPALETTE hpal = NULL;
    PPALETTE ppal;
    ULONG i, cjSize;

    ppal = PALETTE_AllocPalWithHandle(PAL_INDEXED, cEntries, NULL, 0, 0, 0);
    if (ppal == NULL)
    {
        return NULL;
    }

    cjSize = FIELD_OFFSET(LOGPALETTE, palPalEntry[cEntries]);

    _SEH2_TRY
    {
        ProbeForRead(plogpalUser, cjSize, 1);

        for (i = 0; i < cEntries; i++)
        {
            ppal->IndexedColors[i] = plogpalUser->palPalEntry[i];
        }
    }
    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
    {
        GDIOBJ_vDeleteObject(&ppal->BaseObject);
        _SEH2_YIELD(return NULL);
    }
    _SEH2_END;

    PALETTE_ValidateFlags(ppal->IndexedColors, cEntries);
    hpal = ppal->BaseObject.hHmgr;
    PALETTE_UnlockPalette(ppal);

    return hpal;
}
Пример #6
0
HBITMAP
APIENTRY
NtGdiCreateBitmap(
    IN INT nWidth,
    IN INT nHeight,
    IN UINT cPlanes,
    IN UINT cBitsPixel,
    IN OPTIONAL LPBYTE pUnsafeBits)
{
    HBITMAP hbmp;
    ULONG cRealBpp, cjWidthBytes, iFormat;
    ULONGLONG cjSize;
    PSURFACE psurf;

    /* Calculate bitmap format and real bits per pixel. */
    iFormat = BitmapFormat(cBitsPixel * cPlanes, BI_RGB);
    cRealBpp = gajBitsPerFormat[iFormat];

    /* Calculate width and image size in bytes */
    cjWidthBytes = WIDTH_BYTES_ALIGN16(nWidth, cRealBpp);
    cjSize = (ULONGLONG)cjWidthBytes * nHeight;

    /* Check parameters (possible overflow of cjSize!) */
    if ((iFormat == 0) || (nWidth <= 0) || (nWidth >= 0x8000000) || (nHeight <= 0) ||
        (cBitsPixel > 32) || (cPlanes > 32) || (cjSize >= 0x100000000ULL))
    {
        DPRINT1("Invalid bitmap format! Width=%d, Height=%d, Bpp=%u, Planes=%u\n",
                nWidth, nHeight, cBitsPixel, cPlanes);
        EngSetLastError(ERROR_INVALID_PARAMETER);
        return NULL;
    }

    /* Allocate the surface (but don't set the bits) */
    psurf = SURFACE_AllocSurface(STYPE_BITMAP,
                                 nWidth,
                                 nHeight,
                                 iFormat,
                                 0,
                                 0,
                                 NULL);
    if (!psurf)
    {
        DPRINT1("SURFACE_AllocSurface failed.\n");
        return NULL;
    }

    /* Mark as API and DDB bitmap */
    psurf->flags |= (API_BITMAP | DDB_SURFACE);

    /* Check if we have bits to set */
    if (pUnsafeBits)
    {
        /* Protect with SEH and copy the bits */
        _SEH2_TRY
        {
            ProbeForRead(pUnsafeBits, (SIZE_T)cjSize, 1);
            UnsafeSetBitmapBits(psurf, 0, pUnsafeBits);
        }
        _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
        {
            GDIOBJ_vDeleteObject(&psurf->BaseObject);
            _SEH2_YIELD(return NULL;)
        }
        _SEH2_END
    }
    else
    {
Пример #7
0
HPEN
APIENTRY
IntGdiExtCreatePen(
    DWORD dwPenStyle,
    DWORD dwWidth,
    IN ULONG ulBrushStyle,
    IN ULONG ulColor,
    IN ULONG_PTR ulClientHatch,
    IN ULONG_PTR ulHatch,
    DWORD dwStyleCount,
    PULONG pStyle,
    IN ULONG cjDIB,
    IN BOOL bOldStylePen,
    IN OPTIONAL HBRUSH hbrush)
{
    HPEN hPen;
    PBRUSH pbrushPen;
    static const BYTE PatternAlternate[] = {0x55, 0x55, 0x55, 0};
    static const BYTE PatternDash[] = {0xFF, 0xFF, 0xC0, 0};
    static const BYTE PatternDot[] = {0xE3, 0x8E, 0x38, 0};
    static const BYTE PatternDashDot[] = {0xFF, 0x81, 0xC0, 0};
    static const BYTE PatternDashDotDot[] = {0xFF, 0x8E, 0x38, 0};

    dwWidth = abs(dwWidth);

    if ( (dwPenStyle & PS_STYLE_MASK) == PS_NULL)
    {
        return StockObjects[NULL_PEN];
    }

    if (bOldStylePen)
    {
        pbrushPen = PEN_AllocPenWithHandle();
    }
    else
    {
        pbrushPen = PEN_AllocExtPenWithHandle();
    }

    if (!pbrushPen)
    {
        EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
        DPRINT("Can't allocate pen\n");
        return 0;
    }
    hPen = pbrushPen->BaseObject.hHmgr;

    // If nWidth is zero, the pen is a single pixel wide, regardless of the current transformation.
    if ((bOldStylePen) && (!dwWidth) && ((dwPenStyle & PS_STYLE_MASK) != PS_SOLID))
        dwWidth = 1;

    pbrushPen->lWidth = dwWidth;
    pbrushPen->eWidth = (FLOAT)pbrushPen->lWidth;
    pbrushPen->ulPenStyle = dwPenStyle;
    pbrushPen->BrushAttr.lbColor = ulColor;
    pbrushPen->iBrushStyle = ulBrushStyle;
    // FIXME: Copy the bitmap first ?
    pbrushPen->hbmClient = (HANDLE)ulClientHatch;
    pbrushPen->dwStyleCount = dwStyleCount;
    pbrushPen->pStyle = pStyle;

    pbrushPen->flAttrs = bOldStylePen ? BR_IS_OLDSTYLEPEN : BR_IS_PEN;

    // If dwPenStyle is PS_COSMETIC, the width must be set to 1.
    if ( !(bOldStylePen) && ((dwPenStyle & PS_TYPE_MASK) == PS_COSMETIC) && ( dwWidth != 1) )
        goto ExitCleanup;

    switch (dwPenStyle & PS_STYLE_MASK)
    {
    case PS_NULL:
        pbrushPen->flAttrs |= BR_IS_NULL;
        break;

    case PS_SOLID:
        pbrushPen->flAttrs |= BR_IS_SOLID;
        break;

    case PS_ALTERNATE:
        pbrushPen->flAttrs |= BR_IS_BITMAP;
        pbrushPen->hbmPattern = GreCreateBitmap(24, 1, 1, 1, (LPBYTE)PatternAlternate);
        break;

    case PS_DOT:
        pbrushPen->flAttrs |= BR_IS_BITMAP;
        pbrushPen->hbmPattern = GreCreateBitmap(24, 1, 1, 1, (LPBYTE)PatternDot);
        break;

    case PS_DASH:
        pbrushPen->flAttrs |= BR_IS_BITMAP;
        pbrushPen->hbmPattern = GreCreateBitmap(24, 1, 1, 1, (LPBYTE)PatternDash);
        break;

    case PS_DASHDOT:
        pbrushPen->flAttrs |= BR_IS_BITMAP;
        pbrushPen->hbmPattern = GreCreateBitmap(24, 1, 1, 1, (LPBYTE)PatternDashDot);
        break;

    case PS_DASHDOTDOT:
        pbrushPen->flAttrs |= BR_IS_BITMAP;
        pbrushPen->hbmPattern = GreCreateBitmap(24, 1, 1, 1, (LPBYTE)PatternDashDotDot);
        break;

    case PS_INSIDEFRAME:
        pbrushPen->flAttrs |= (BR_IS_SOLID | BR_IS_INSIDEFRAME);
        break;

    case PS_USERSTYLE:
        if ((dwPenStyle & PS_TYPE_MASK) == PS_COSMETIC)
        {
            /* FIXME: PS_USERSTYLE workaround */
            DPRINT1("PS_COSMETIC | PS_USERSTYLE not handled\n");
            pbrushPen->flAttrs |= BR_IS_SOLID;
            break;
        }
        else
        {
            UINT i;
            BOOL has_neg = FALSE, all_zero = TRUE;

            for(i = 0; (i < dwStyleCount) && !has_neg; i++)
            {
                has_neg = has_neg || (((INT)(pStyle[i])) < 0);
                all_zero = all_zero && (pStyle[i] == 0);
            }

            if(all_zero || has_neg)
            {
                goto ExitCleanup;
            }
        }
        /* FIXME: What style here? */
        pbrushPen->flAttrs |= 0;
        break;

    default:
        DPRINT1("IntGdiExtCreatePen unknown penstyle %x\n", dwPenStyle);
    }

    PEN_UnlockPen(pbrushPen);
    return hPen;

ExitCleanup:
    EngSetLastError(ERROR_INVALID_PARAMETER);
    pbrushPen->pStyle = NULL;
    GDIOBJ_vDeleteObject(&pbrushPen->BaseObject);

    return NULL;
}
Пример #8
0
PSURFACE
NTAPI
SURFACE_AllocSurface(
    _In_ USHORT iType,
    _In_ ULONG cx,
    _In_ ULONG cy,
    _In_ ULONG iFormat,
    _In_ ULONG fjBitmap,
    _In_opt_ ULONG cjWidth,
    _In_opt_ ULONG cjBufSize,
    _In_opt_ PVOID pvBits)
{
    ULONG cBitsPixel, cjBits, cjObject;
    PSURFACE psurf;
    SURFOBJ *pso;
    PVOID pvSection;

    NT_ASSERT(!pvBits || (iType == STYPE_BITMAP));
    NT_ASSERT((iFormat <= BMF_32BPP) || (cjBufSize != 0));
    NT_ASSERT((LONG)cy > 0);

    /* Verify format */
    if ((iFormat < BMF_1BPP) || (iFormat > BMF_PNG))
    {
        DPRINT1("Invalid bitmap format: %lu\n", iFormat);
        return NULL;
    }

    /* Get bits per pixel from the format */
    cBitsPixel = gajBitsPerFormat[iFormat];

    /* Are bits and a width in bytes given? */
    if (pvBits && cjWidth)
    {
        /* Align the width (Windows compatibility, drivers expect that) */
        cjWidth = WIDTH_BYTES_ALIGN32((cjWidth << 3) / cBitsPixel, cBitsPixel);
    }
    else
    {
        /* Calculate width from the bitmap width in pixels */
        cjWidth = WIDTH_BYTES_ALIGN32(cx, cBitsPixel);
    }

    /* Is this an uncompressed format? */
    if (iFormat <= BMF_32BPP)
    {
        /* Calculate the correct bitmap size in bytes */
        if (!NT_SUCCESS(RtlULongMult(cjWidth, cy, &cjBits)))
        {
            DPRINT1("Overflow calculating size: cjWidth %lu, cy %lu\n",
                    cjWidth, cy);
            return NULL;
        }

        /* Did we get a buffer and size? */
        if ((pvBits != NULL) && (cjBufSize != 0))
        {
            /* Make sure the buffer is large enough */
            if (cjBufSize < cjBits)
            {
                DPRINT1("Buffer is too small, required: %lu, got %lu\n",
                        cjBits, cjBufSize);
                return NULL;
            }
        }
    }
    else
    {
        /* Compressed format, use the provided size */
        NT_ASSERT(cjBufSize != 0);
        cjBits = cjBufSize;
    }

    /* Check if we need an extra large object */
    if ((iType == STYPE_BITMAP) && (pvBits == NULL) &&
        !(fjBitmap & BMF_USERMEM) && !(fjBitmap & BMF_KMSECTION))
    {
        /* Allocate an object large enough to hold the bits */
        cjObject = sizeof(SURFACE) + cjBits;
    }
    else
    {
        /* Otherwise just allocate the SURFACE structure */
        cjObject = sizeof(SURFACE);
    }

    /* Check for arithmetic overflow */
    if (cjObject < sizeof(SURFACE))
    {
        /* Fail! */
        DPRINT1("Overflow calculating cjObject: cjBits %lu\n", cjBits);
        return NULL;
    }

    /* Allocate a SURFACE object */
    psurf = (PSURFACE)GDIOBJ_AllocObjWithHandle(GDI_OBJECT_TYPE_BITMAP, cjObject);
    if (!psurf)
    {
        return NULL;
    }

    /* Initialize the basic fields */
    pso = &psurf->SurfObj;
    pso->hsurf = psurf->BaseObject.hHmgr;
    pso->sizlBitmap.cx = cx;
    pso->sizlBitmap.cy = cy;
    pso->iBitmapFormat = iFormat;
    pso->iType = iType;
    pso->fjBitmap = (USHORT)fjBitmap;
    pso->iUniq = InterlockedIncrement(&giUniqueSurface);
    pso->cjBits = cjBits;

    /* Check if we need a bitmap buffer */
    if (iType == STYPE_BITMAP)
    {
        /* Check if we got one or if we need to allocate one */
        if (pvBits != NULL)
        {
            /* Use the caller provided buffer */
            pso->pvBits = pvBits;
        }
        else if (fjBitmap & BMF_USERMEM)
        {
            /* User mode memory was requested */
            pso->pvBits = EngAllocUserMem(cjBits, 0);

            /* Check for failure */
            if (!pso->pvBits)
            {
                GDIOBJ_vDeleteObject(&psurf->BaseObject);
                return NULL;
            }
        }
        else if (fjBitmap & BMF_KMSECTION)
        {
            /* Use a kernel mode section */
            pso->pvBits = EngAllocSectionMem(&pvSection,
                                             (fjBitmap & BMF_NOZEROINIT) ?
                                                 0 : FL_ZERO_MEMORY,
                                             cjBits, TAG_DIB);

            /* Check for failure */
            if (!pso->pvBits)
            {
                GDIOBJ_vDeleteObject(&psurf->BaseObject);
                return NULL;
            }

            /* Free the section already, but keep the mapping */
            EngFreeSectionMem(pvSection, NULL);
        }
        else
        {
            /* Buffer is after the object */
            pso->pvBits = psurf + 1;

            /* Zero the buffer, except requested otherwise */
            if (!(fjBitmap & BMF_NOZEROINIT))
            {
                RtlZeroMemory(pso->pvBits, cjBits);
            }
        }

        /* Set pvScan0 and lDelta */
        if (fjBitmap & BMF_TOPDOWN)
        {
            /* Topdown is the normal way */
            pso->pvScan0 = pso->pvBits;
            pso->lDelta = cjWidth;
        }
        else
        {
            /* Inversed bitmap (bottom up) */
            pso->pvScan0 = ((PCHAR)pso->pvBits + pso->cjBits - cjWidth);
            pso->lDelta = -(LONG)cjWidth;
        }
    }
    else
    {
        /* There are no bitmap bits */
        pso->pvScan0 = pso->pvBits = NULL;
        pso->lDelta = 0;
    }

    /* Assign a default palette and increment its reference count */
    SURFACE_vSetPalette(psurf, appalSurfaceDefault[iFormat]);

    return psurf;
}
Пример #9
0
/* Mostly inspired from wine code.
 * We use low level functions because:
 *  - at this point, the icon bitmap could have a different bit depth than the DC,
 *    making it thus impossible to use NtCreateCompatibleDC and selecting the bitmap.
 *    This happens after a mode setting change.
 *  - it avoids massive GDI objects locking when only the destination surface needs it.
 *  - It makes (small) performance gains.
 */
BOOL
UserDrawIconEx(
    HDC hDc,
    INT xLeft,
    INT yTop,
    PCURICON_OBJECT pIcon,
    INT cxWidth,
    INT cyHeight,
    UINT istepIfAniCur,
    HBRUSH hbrFlickerFreeDraw,
    UINT diFlags)
{
    PSURFACE psurfDest, psurfMask, psurfColor; //, psurfOffScreen = NULL;
    PDC pdc = NULL;
    BOOL Ret = FALSE;
    HBITMAP hbmMask, hbmColor, hbmAlpha;
    BOOL bOffScreen;
    RECTL rcDest, rcSrc;
    CLIPOBJ* pdcClipObj = NULL;
    EXLATEOBJ exlo;
    
    /* Stupid case */
    if((diFlags & DI_NORMAL) == 0)
    {
        ERR("DrawIconEx called without mask or color bitmap to draw.\n");
        return FALSE;
    }

    if (pIcon->CURSORF_flags & CURSORF_ACON)
    {
        ACON* pAcon = (ACON*)pIcon;
        if(istepIfAniCur >= pAcon->cicur)
        {
            ERR("NtUserDrawIconEx: istepIfAniCur too big!\n");
            return FALSE;
        }
        pIcon = pAcon->aspcur[pAcon->aicur[istepIfAniCur]];
    }

    hbmMask = pIcon->hbmMask;
    hbmColor = pIcon->hbmColor;
    hbmAlpha = pIcon->hbmAlpha;
    
    /*
     * Get our objects. 
     * Shared locks are enough, we are only reading those bitmaps
     */
    psurfMask = SURFACE_ShareLockSurface(hbmMask);
    if(psurfMask == NULL)
    {
        ERR("Unable to lock the mask surface.\n");
        return FALSE;
    }
    
    /* Color bitmap is not mandatory */
    if(hbmColor == NULL)
    {
        /* But then the mask bitmap must have the information in it's bottom half */
        ASSERT(psurfMask->SurfObj.sizlBitmap.cy == 2*pIcon->cy);
        psurfColor = NULL;
    }
    else if ((psurfColor = SURFACE_ShareLockSurface(hbmColor)) == NULL)
    {
        ERR("Unable to lock the color bitmap.\n");
        SURFACE_ShareUnlockSurface(psurfMask);
        return FALSE;
    }
    
    pdc = DC_LockDc(hDc);
    if(!pdc)
    {
        ERR("Could not lock the destination DC.\n");
        SURFACE_ShareUnlockSurface(psurfMask);
        if(psurfColor) SURFACE_ShareUnlockSurface(psurfColor);
        return FALSE;
    }
    /* Calculate destination rectangle */
    RECTL_vSetRect(&rcDest, xLeft, yTop, xLeft + cxWidth, yTop + cyHeight);
    IntLPtoDP(pdc, (LPPOINT)&rcDest, 2);
    RECTL_vOffsetRect(&rcDest, pdc->ptlDCOrig.x, pdc->ptlDCOrig.y);
    
    /* Prepare the underlying surface */
    DC_vPrepareDCsForBlit(pdc, rcDest, NULL, rcDest);

    /* We now have our destination surface and rectangle */
    psurfDest = pdc->dclevel.pSurface;
    
    if(psurfDest == NULL)
    {
        /* Empty DC */
        DC_vFinishBlit(pdc, NULL);
        DC_UnlockDc(pdc);
        SURFACE_ShareUnlockSurface(psurfMask);
        if(psurfColor) SURFACE_ShareUnlockSurface(psurfColor);
        return FALSE;
    }
    
    /* Set source rect */
    RECTL_vSetRect(&rcSrc, 0, 0, pIcon->cx, pIcon->cy);

    /* Fix width parameter, if needed */
    if (!cxWidth)
    {
        if(diFlags & DI_DEFAULTSIZE)
            cxWidth = is_icon(pIcon) ? 
                UserGetSystemMetrics(SM_CXICON) : UserGetSystemMetrics(SM_CXCURSOR);
        else
            cxWidth = pIcon->cx;
    }
    
    /* Fix height parameter, if needed */
    if (!cyHeight)
    {
        if(diFlags & DI_DEFAULTSIZE)
            cyHeight = is_icon(pIcon) ? 
                UserGetSystemMetrics(SM_CYICON) : UserGetSystemMetrics(SM_CYCURSOR);
        else
            cyHeight = pIcon->cy;
    }

    /* Should we render off-screen? */
    bOffScreen = hbrFlickerFreeDraw && 
        (GDI_HANDLE_GET_TYPE(hbrFlickerFreeDraw) == GDI_OBJECT_TYPE_BRUSH);

    if (bOffScreen)
    {
        /* Yes: Allocate and paint the offscreen surface */
        EBRUSHOBJ eboFill;
        PBRUSH pbrush = BRUSH_ShareLockBrush(hbrFlickerFreeDraw);
        
        TRACE("Performing off-screen rendering.\n");
        
        if(!pbrush)
        {
            ERR("Failed to get brush object.\n");
            goto Cleanup;
        }

#if 0 //We lock the hdc surface during the whole function it makes no sense to use an offscreen surface for "flicker free" drawing
        psurfOffScreen = SURFACE_AllocSurface(STYPE_BITMAP,
            cxWidth, cyHeight, psurfDest->SurfObj.iBitmapFormat,
            0, 0, NULL);
        if(!psurfOffScreen)
        {
            ERR("Failed to allocate the off-screen surface.\n");
            BRUSH_ShareUnlockBrush(pbrush);
            goto Cleanup;
        }
        
        /* Paint the brush */
        EBRUSHOBJ_vInit(&eboFill, pbrush, psurfOffScreen, 0x00FFFFFF, 0, NULL);
        RECTL_vSetRect(&rcDest, 0, 0, cxWidth, cyHeight);
        
        Ret = IntEngBitBlt(&psurfOffScreen->SurfObj,
            NULL,
            NULL,
            NULL,
            NULL,
            &rcDest,
            NULL,
            NULL,
            &eboFill.BrushObject,
            &pbrush->ptOrigin,
            ROP4_PATCOPY);

        /* Clean up everything */
        EBRUSHOBJ_vCleanup(&eboFill);
        BRUSH_ShareUnlockBrush(pbrush);
            
        if(!Ret)
        {
            ERR("Failed to paint the off-screen surface.\n");
            goto Cleanup;
        }
        
        /* We now have our destination surface */
        psurfDest = psurfOffScreen;
#else
        pdcClipObj = pdc->rosdc.CombinedClip;
        /* Paint the brush */
        EBRUSHOBJ_vInit(&eboFill, pbrush, psurfDest, 0x00FFFFFF, 0, NULL);
        
        Ret = IntEngBitBlt(&psurfDest->SurfObj,
            NULL,
            NULL,
            pdcClipObj,
            NULL,
            &rcDest,
            NULL,
            NULL,
            &eboFill.BrushObject,
            &pbrush->ptOrigin,
            ROP4_PATCOPY);

        /* Clean up everything */
        EBRUSHOBJ_vCleanup(&eboFill);
        BRUSH_ShareUnlockBrush(pbrush);
            
        if(!Ret)
        {
            ERR("Failed to paint the off-screen surface.\n");
            goto Cleanup;
        }
#endif
    }
    else
    {
        /* We directly draw to the DC */
        TRACE("Performing on screen rendering.\n");
        pdcClipObj = pdc->rosdc.CombinedClip;
        // psurfOffScreen = NULL;
    }

    /* Now do the rendering */
	if(hbmAlpha && ((diFlags & DI_NORMAL) == DI_NORMAL))
	{
	    BLENDOBJ blendobj = { {AC_SRC_OVER, 0, 255, AC_SRC_ALPHA } };
        PSURFACE psurf = NULL;

        psurf = SURFACE_ShareLockSurface(hbmAlpha);
        if(!psurf)
        {
            ERR("SURFACE_LockSurface failed!\n");
            goto NoAlpha;
        }
        
        /* Initialize color translation object */
        EXLATEOBJ_vInitialize(&exlo, psurf->ppal, psurfDest->ppal, 0xFFFFFFFF, 0xFFFFFFFF, 0);
        
        /* Now do it */
        Ret = IntEngAlphaBlend(&psurfDest->SurfObj,
                               &psurf->SurfObj,
                               pdcClipObj,
                               &exlo.xlo,
                               &rcDest,
                               &rcSrc,
                               &blendobj);
        
        EXLATEOBJ_vCleanup(&exlo);
        SURFACE_ShareUnlockSurface(psurf);
        if(Ret) goto done;
		ERR("NtGdiAlphaBlend failed!\n");
    }
NoAlpha:
    if (diFlags & DI_MASK)
    {
        DWORD rop4 = (diFlags & DI_IMAGE) ? ROP4_SRCAND : ROP4_SRCCOPY;
        
        EXLATEOBJ_vInitSrcMonoXlate(&exlo, psurfDest->ppal, 0x00FFFFFF, 0);
        
        Ret = IntEngStretchBlt(&psurfDest->SurfObj,
                               &psurfMask->SurfObj,
                               NULL,
                               pdcClipObj,
                               &exlo.xlo,
                               NULL,
                               &rcDest,
                               &rcSrc,
                               NULL,
                               NULL,
                               NULL,
                               rop4);
        
        EXLATEOBJ_vCleanup(&exlo);

        if(!Ret)
        {
            ERR("Failed to mask the bitmap data.\n");
            goto Cleanup;
        }
    }

    if(diFlags & DI_IMAGE)
    {
		if (psurfColor)
        {
            DWORD rop4 = (diFlags & DI_MASK) ? ROP4_SRCINVERT : ROP4_SRCCOPY ;
            
            EXLATEOBJ_vInitialize(&exlo, psurfColor->ppal, psurfDest->ppal, 0x00FFFFFF, 0x00FFFFFF, 0);
            
            Ret = IntEngStretchBlt(&psurfDest->SurfObj,
                                   &psurfColor->SurfObj,
                                   NULL,
                                   pdcClipObj,
                                   &exlo.xlo,
                                   NULL,
                                   &rcDest,
                                   &rcSrc,
                                   NULL,
                                   NULL,
                                   NULL,
                                   rop4);
        
            EXLATEOBJ_vCleanup(&exlo);

            if(!Ret)
            {
                ERR("Failed to render the icon bitmap.\n");
                goto Cleanup;
            }
        }
        else
        {
            /* Mask bitmap holds the information in its bottom half */
            DWORD rop4 = (diFlags & DI_MASK) ? ROP4_SRCINVERT : ROP4_SRCCOPY;
            RECTL_vOffsetRect(&rcSrc, 0, pIcon->cy);
            
            EXLATEOBJ_vInitSrcMonoXlate(&exlo, psurfDest->ppal, 0x00FFFFFF, 0);
        
            Ret = IntEngStretchBlt(&psurfDest->SurfObj,
                                   &psurfMask->SurfObj,
                                   NULL,
                                   pdcClipObj,
                                   &exlo.xlo,
                                   NULL,
                                   &rcDest,
                                   &rcSrc,
                                   NULL,
                                   NULL,
                                   NULL,
                                   rop4);
            
            EXLATEOBJ_vCleanup(&exlo);

            if(!Ret)
            {
                ERR("Failed to render the icon bitmap.\n");
                goto Cleanup;
            }
        }
    }

done:
#if 0
    /* We're done. Was it a double buffered draw ? */
    if(bOffScreen)
    {
        /* Yes. Draw it back to our DC */
        POINTL ptSrc = {0, 0};

        /* Calculate destination rectangle */
        RECTL_vSetRect(&rcDest, xLeft, yTop, xLeft + cxWidth, yTop + cyHeight);
        IntLPtoDP(pdc, (LPPOINT)&rcDest, 2);
        RECTL_vOffsetRect(&rcDest, pdc->ptlDCOrig.x, pdc->ptlDCOrig.y);
        
        /* Get the clip object */
        pdcClipObj = pdc->rosdc.CombinedClip;
        
        /* We now have our destination surface and rectangle */
        psurfDest = pdc->dclevel.pSurface;
        
        /* Color translation */
        EXLATEOBJ_vInitialize(&exlo, psurfOffScreen->ppal, psurfDest->ppal, 0x00FFFFFF, 0x00FFFFFF, 0);
        
        /* Blt it! */
        Ret = IntEngBitBlt(&psurfDest->SurfObj,
                           &psurfOffScreen->SurfObj,
                           NULL,
                           pdcClipObj,
                           &exlo.xlo,
                           &rcDest,
                           &ptSrc,
                           NULL,
                           NULL,
                           NULL,
                           ROP4_SRCCOPY);
                           
        EXLATEOBJ_vCleanup(&exlo);
    }
#endif
Cleanup:
    if(pdc)
    {
        DC_vFinishBlit(pdc, NULL);
        DC_UnlockDc(pdc);
    }

#if 0
    /* Delete off screen rendering surface */
    if(psurfOffScreen)
        GDIOBJ_vDeleteObject(&psurfOffScreen->BaseObject);
#endif

    /* Unlock other surfaces */
    SURFACE_ShareUnlockSurface(psurfMask);
    if(psurfColor) SURFACE_ShareUnlockSurface(psurfColor);

    return Ret;
}