You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
3949 lines
93 KiB
3949 lines
93 KiB
/******************************Module*Header*******************************\
|
|
* Module Name: umpdeng.c
|
|
* This file contains stubs for calls made by umpdeng.c from gdi32.dll
|
|
*
|
|
* Created: 8/5/97
|
|
* Author: Lingyun Wang [lingyunw]
|
|
*
|
|
* Copyright (c) 1997-1999 Microsoft Corporation
|
|
*
|
|
\**************************************************************************/
|
|
|
|
|
|
#include "precomp.hxx"
|
|
|
|
#if !defined(_GDIPLUS_)
|
|
|
|
//
|
|
// Macro for extracting the topmost UMPDOBJS structure
|
|
// associated with the current thread.
|
|
//
|
|
// Put the following line at the beginning of each NtGdi...
|
|
// function (after all other local variable declarations):
|
|
//
|
|
// EXTRACT_THREAD_UMPDOBJS retVal;
|
|
//
|
|
// where retVal is the error return value. If the function doesn't return
|
|
// any value, simply omit the retVal.
|
|
//
|
|
|
|
#define EXTRACT_THREAD_UMPDOBJS \
|
|
PUMPDOBJ pUMObjs = (PUMPDOBJ) W32GetCurrentThread()->pUMPDObj; \
|
|
if (pUMObjs) \
|
|
pUMObjs->vSetFlags(UMPDOBJ_ENGCALL); \
|
|
else \
|
|
return
|
|
|
|
#define FIXUP_THREAD_UMPDOBJS \
|
|
if (pUMObjs) \
|
|
pUMObjs->vClearFlags(UMPDOBJ_ENGCALL);
|
|
|
|
|
|
//
|
|
// determine whether a BRUSHOBJ is a pattern brush
|
|
//
|
|
|
|
#define ISPATBRUSH(_pbo) ((_pbo) && (_pbo)->iSolidColor == 0xffffffff)
|
|
#define MIXNEEDMASK(_mix) (((_mix) & 0xf) != (((_mix) >> 8) & 0xf))
|
|
|
|
//
|
|
// Map a user-mode BRUSHOBJ to its kernel-mode counterpart
|
|
//
|
|
|
|
#define MAP_UM_BRUSHOBJ(pUMObjs, pbo, pboTemp) \
|
|
{ \
|
|
BRUSHOBJ *tempVar; \
|
|
tempVar = (pUMObjs)->GetDDIOBJ(pbo); \
|
|
pbo = tempVar ? tempVar : CaptureAndFakeBRUSHOBJ(pbo, pboTemp); \
|
|
}
|
|
|
|
inline BOOL
|
|
PROBEDISPATBRUSH(BRUSHOBJ *pbo)
|
|
{
|
|
BRUSHOBJ tmpBo;
|
|
BOOL bRet = FALSE;
|
|
__try
|
|
{
|
|
tmpBo = ProbeAndReadStructure(pbo, BRUSHOBJ);
|
|
if (ISPATBRUSH(&tmpBo))
|
|
bRet = TRUE;
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
}
|
|
return bRet;
|
|
}
|
|
|
|
//
|
|
// "Manufacture" a kernel-mode BRUSHOBJ structure using
|
|
// the user-mode BRUSHOBJ as template
|
|
//
|
|
|
|
BRUSHOBJ *
|
|
CaptureAndFakeBRUSHOBJ(
|
|
BRUSHOBJ *pboUm,
|
|
BRUSHOBJ *pboKm
|
|
)
|
|
|
|
{
|
|
if (pboUm)
|
|
{
|
|
__try
|
|
{
|
|
// Copy user-mode BRUSHOBJ structure into kernel-mode memory
|
|
|
|
*pboKm = ProbeAndReadStructure(pboUm, BRUSHOBJ);
|
|
|
|
// Succeed only if BRUSHOBJ represents a solid color brush
|
|
|
|
if (!ISPATBRUSH(pboKm))
|
|
pboKm->pvRbrush = NULL;
|
|
else
|
|
pboKm = NULL;
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
pboKm = NULL;
|
|
}
|
|
}
|
|
else
|
|
pboKm = NULL;
|
|
|
|
return pboKm;
|
|
}
|
|
|
|
|
|
//
|
|
// Capture a user-mode CLIPOBJ that orignated from EngCreateClip
|
|
//
|
|
|
|
CLIPOBJ *
|
|
CaptureAndMungeCLIPOBJ(
|
|
CLIPOBJ *pcoUm,
|
|
CLIPOBJ *pcoKm,
|
|
SIZEL *szLimit
|
|
)
|
|
|
|
{
|
|
CLIPOBJ co;
|
|
|
|
//
|
|
// Capture user-mode CLIPOBJ structure into a temporary buffer
|
|
//
|
|
|
|
if (pcoUm)
|
|
{
|
|
__try
|
|
{
|
|
co = ProbeAndReadStructure(pcoUm, CLIPOBJ);
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
pcoKm = NULL;
|
|
}
|
|
|
|
//
|
|
// Munge the relevant fields in kernel-mode CLIPOBJ
|
|
//
|
|
|
|
if (pcoKm)
|
|
{
|
|
switch (co.iDComplexity)
|
|
{
|
|
case DC_RECT:
|
|
|
|
if (szLimit)
|
|
{
|
|
co.rclBounds.left = max(0, co.rclBounds.left);
|
|
co.rclBounds.top = max(0, co.rclBounds.top);
|
|
co.rclBounds.right = min(szLimit->cx, co.rclBounds.right);
|
|
co.rclBounds.bottom = min(szLimit->cy, co.rclBounds.bottom);
|
|
}
|
|
|
|
pcoKm->rclBounds = co.rclBounds;
|
|
|
|
// fall through
|
|
|
|
case DC_TRIVIAL:
|
|
|
|
pcoKm->iDComplexity = co.iDComplexity;
|
|
break;
|
|
|
|
default:
|
|
|
|
WARNING("User-mode CLIPOBJ is not DC_TRIVIAL or DC_RECT\n");
|
|
pcoKm = NULL;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ASSERTGDI(pcoKm == NULL, "CaptureAndMungeCLIPOBJ: invalid pcoKm\n");
|
|
}
|
|
|
|
return pcoKm;
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* GetSTROBJGlyphMode
|
|
*
|
|
* helper function to determine the Glyphmode based on strobj
|
|
*
|
|
* History:
|
|
* 26-Sept-1997 -by- Lingyun Wang [lingyunw]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
__inline
|
|
ULONG GetSTROBJGlyphMode (STROBJ *pstro)
|
|
{
|
|
return (((ESTROBJ*)pstro)->prfo->prfnt->ulContent);
|
|
}
|
|
|
|
__inline
|
|
BOOL bOrder (RECTL *prcl)
|
|
{
|
|
return ((prcl->left < prcl->right) && (prcl->top < prcl->bottom));
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* helper functions to copy user memory
|
|
*
|
|
* CaptureRECTL CapturePOINTL CapturePOINTFIX
|
|
* CaptureLINEATTRS CaptureCOLORADJUSTMENT
|
|
*
|
|
* Note: prclFrom points to the captured rect on the way back
|
|
* Note: Needs to be called within try/except
|
|
*
|
|
* History:
|
|
* 26-Sept-1997 -by- Lingyun Wang [lingyunw]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
__inline
|
|
VOID CaptureRECTL (RECTL **pprclFrom, RECTL *prclTo)
|
|
{
|
|
if (*pprclFrom)
|
|
{
|
|
*prclTo = ProbeAndReadStructure(*pprclFrom,RECTL);
|
|
|
|
//
|
|
// repoint pprclFrom to prclTo
|
|
//
|
|
*pprclFrom = prclTo;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
__inline
|
|
VOID CapturePOINTL (POINTL **ppptlFrom, POINTL *pptlTo)
|
|
{
|
|
if (*ppptlFrom)
|
|
{
|
|
*pptlTo = ProbeAndReadStructure(*ppptlFrom,POINTL);
|
|
|
|
*ppptlFrom = pptlTo;
|
|
}
|
|
return;
|
|
}
|
|
|
|
__inline
|
|
VOID CapturePOINTFIX (POINTFIX **ppptfxFrom, POINTFIX *pptfxTo)
|
|
{
|
|
if (*ppptfxFrom)
|
|
{
|
|
*pptfxTo = ProbeAndReadStructure(*ppptfxFrom,POINTFIX);
|
|
|
|
*ppptfxFrom = pptfxTo;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
//
|
|
// the calling routine needs to free pStyle
|
|
//
|
|
// Note: plineFrom will be changed to plineTo upon returning from this routine
|
|
// so to save some changes into the lower level calls
|
|
//
|
|
__inline
|
|
BOOL bCaptureLINEATTRS (LINEATTRS **pplineFrom, LINEATTRS *plineTo)
|
|
{
|
|
BOOL bRet = TRUE;
|
|
|
|
if (*pplineFrom)
|
|
{
|
|
PFLOAT_LONG pstyle = NULL;
|
|
|
|
__try
|
|
{
|
|
|
|
*plineTo = ProbeAndReadStructure(*pplineFrom,LINEATTRS);
|
|
|
|
if (plineTo->pstyle)
|
|
{
|
|
if (BALLOC_OVERFLOW1(plineTo->cstyle, FLOAT_LONG))
|
|
return FALSE;
|
|
|
|
ProbeForRead(plineTo->pstyle, plineTo->cstyle*sizeof(FLOAT_LONG), sizeof(BYTE));
|
|
|
|
pstyle = (PFLOAT_LONG)PALLOCNOZ(plineTo->cstyle*sizeof(FLOAT_LONG), UMPD_MEMORY_TAG);
|
|
|
|
if (!pstyle)
|
|
{
|
|
//
|
|
// so we won't free it later
|
|
//
|
|
plineTo->pstyle = NULL;
|
|
bRet = FALSE;
|
|
}
|
|
else
|
|
{
|
|
RtlCopyMemory(pstyle, plineTo->pstyle, plineTo->cstyle*sizeof(FLOAT_LONG));
|
|
|
|
plineTo->pstyle = pstyle;
|
|
}
|
|
}
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
WARNING ("bCaptureLINEATTRS -- exception in try/except \n");
|
|
|
|
if (pstyle)
|
|
VFREEMEM(pstyle);
|
|
|
|
bRet = FALSE;
|
|
}
|
|
|
|
*pplineFrom = plineTo;
|
|
}
|
|
|
|
return bRet;
|
|
}
|
|
|
|
__inline
|
|
VOID CaptureCOLORADJUSTMENT (COLORADJUSTMENT **ppcaFrom, COLORADJUSTMENT *pcaTo)
|
|
{
|
|
if (*ppcaFrom)
|
|
{
|
|
*pcaTo = ProbeAndReadStructure(*ppcaFrom,COLORADJUSTMENT);
|
|
|
|
*ppcaFrom = pcaTo;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
__inline
|
|
VOID CaptureDWORD (DWORD **ppdwFrom, DWORD *pdwTo)
|
|
{
|
|
if (*ppdwFrom)
|
|
{
|
|
*pdwTo = ProbeAndReadStructure(*ppdwFrom,DWORD);
|
|
|
|
//
|
|
// repoint pprclFrom to prclTo
|
|
//
|
|
*ppdwFrom = pdwTo;
|
|
}
|
|
return;
|
|
}
|
|
|
|
__inline
|
|
VOID CaptureBits (PVOID pv, PVOID pvTmp, ULONG cj)
|
|
{
|
|
if (pv && pvTmp)
|
|
{
|
|
ProbeAndReadBuffer(pv, pvTmp, cj);
|
|
}
|
|
return;
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* bSecureBits bSafeReadBits bSafeCopyBits
|
|
*
|
|
* helper functions to secure or copy user memory
|
|
* These donot need to be called from within try/except
|
|
*
|
|
* History:
|
|
* 26-Sept-1997 -by- Lingyun Wang [lingyunw]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
__inline
|
|
BOOL bSecureBits (PVOID pv, ULONG cj, HANDLE *phSecure)
|
|
{
|
|
BOOL bRet = TRUE;
|
|
|
|
*phSecure = 0;
|
|
|
|
if (pv)
|
|
{
|
|
__try
|
|
{
|
|
ProbeForRead(pv,cj,sizeof(BYTE));
|
|
*phSecure = MmSecureVirtualMemory(pv, cj, PAGE_READONLY);
|
|
|
|
if (*phSecure == 0)
|
|
{
|
|
bRet = FALSE;
|
|
}
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
WARNING ("bSecureBits -- exception in try/except \n");
|
|
bRet = FALSE;
|
|
}
|
|
}
|
|
|
|
return (bRet);
|
|
}
|
|
|
|
__inline
|
|
BOOL bSafeCopyBits (PVOID pv, PVOID pvTmp, ULONG cj)
|
|
{
|
|
BOOL bRet = TRUE;
|
|
|
|
if (pv && pvTmp)
|
|
{
|
|
__try
|
|
{
|
|
ProbeAndWriteBuffer(pv, pvTmp, cj);
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
WARNING ("fail in try/except to write into buffer\n");
|
|
bRet = FALSE;
|
|
}
|
|
|
|
}
|
|
return bRet;
|
|
}
|
|
|
|
__inline
|
|
BOOL bSafeReadBits (PVOID pv, PVOID pvTmp, ULONG cj)
|
|
{
|
|
BOOL bRet = TRUE;
|
|
|
|
if (pv && pvTmp)
|
|
{
|
|
__try
|
|
{
|
|
ProbeAndReadBuffer(pv, pvTmp, cj);
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
WARNING ("fail in try/except to read from buffer\n");
|
|
bRet = FALSE;
|
|
}
|
|
}
|
|
return bRet;
|
|
}
|
|
|
|
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* bCheckSurfaceRect bCheckSurfaceRectSize
|
|
*
|
|
* Check rect and pco against the surface, make sure we are not going to
|
|
* draw outside the surface
|
|
*
|
|
* bCheckSurfacePath
|
|
*
|
|
* Check the path against the surface, make sure not going to draw outside
|
|
* the surface
|
|
*
|
|
* bCheckSurfacePoint
|
|
*
|
|
* Check the point against the surface
|
|
*
|
|
* History:
|
|
* 26-Sept-1997 -by- Lingyun Wang [lingyunw]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
__inline
|
|
BOOL bCheckSurfaceRect(SURFOBJ *pso, RECTL *prcl, CLIPOBJ *pco)
|
|
{
|
|
BOOL bRet = TRUE;
|
|
BOOL bTrivial;
|
|
|
|
if (pso)
|
|
{
|
|
if (pco)
|
|
{
|
|
bTrivial = (pco->iDComplexity == DC_TRIVIAL) ? TRUE : FALSE;
|
|
}
|
|
else
|
|
{
|
|
bTrivial = TRUE;
|
|
}
|
|
|
|
//
|
|
// if no clipping, check against the rectangle.
|
|
//
|
|
if (!bTrivial)
|
|
{
|
|
//
|
|
// there is clipping invloved, check against pco->rclBounds.
|
|
//
|
|
prcl = &(pco->rclBounds);
|
|
}
|
|
|
|
if (prcl)
|
|
{
|
|
if ((prcl->left > prcl->right) || (prcl->top > prcl->bottom))
|
|
{
|
|
WARNING ("prcl not well ordered, returing failure\n");
|
|
bRet = FALSE;
|
|
}
|
|
|
|
if (bRet && ((prcl->right > pso->sizlBitmap.cx) || (prcl->left < 0)||
|
|
(prcl->bottom > pso->sizlBitmap.cy)|| (prcl->top < 0)))
|
|
{
|
|
WARNING ("we might draw outside the surface, returning failure\n");
|
|
bRet = FALSE;
|
|
}
|
|
}
|
|
}
|
|
|
|
return bRet;
|
|
}
|
|
|
|
|
|
__inline
|
|
BOOL bCheckSurfaceRectSize(SURFOBJ *pso, RECTL *prcl, CLIPOBJ *pco,
|
|
ULONG *pcx, ULONG *pcy, BOOL bOrder = TRUE)
|
|
{
|
|
BOOL bRet = TRUE;
|
|
BOOL bTrivial;
|
|
ERECTL rcl(0, 0, 0, 0);
|
|
PRECTL prclBounds = NULL;
|
|
|
|
if (pso)
|
|
{
|
|
if (pco)
|
|
{
|
|
bTrivial = (pco->iDComplexity == DC_TRIVIAL) ? TRUE : FALSE;
|
|
}
|
|
else
|
|
{
|
|
bTrivial = TRUE;
|
|
}
|
|
|
|
//
|
|
// if no clipping, check against the rectangle.
|
|
//
|
|
if (!bTrivial)
|
|
{
|
|
//
|
|
// there is clipping invloved, check against pco->rclBounds.
|
|
//
|
|
prclBounds = &(pco->rclBounds);
|
|
rcl = *prclBounds;
|
|
}
|
|
else
|
|
{
|
|
if (prcl)
|
|
{
|
|
rcl = *prcl;
|
|
}
|
|
}
|
|
|
|
//
|
|
// check the rectangle
|
|
//
|
|
if (bOrder && ((rcl.left > rcl.right) || (rcl.top > rcl.bottom)))
|
|
{
|
|
WARNING ("rcl not well ordered, returing failure\n");
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// check that we are not going outside the surface
|
|
//
|
|
if ((rcl.right > pso->sizlBitmap.cx) || (rcl.left < 0)||
|
|
(rcl.bottom > pso->sizlBitmap.cy)|| (rcl.top < 0))
|
|
{
|
|
WARNING ("we might draw outside the surface, returning failure\n");
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// figure out the size
|
|
//
|
|
if (prclBounds && prcl)
|
|
{
|
|
RECTL rclIntersect;
|
|
|
|
rclIntersect.left = MAX(prclBounds->left, prcl->left);
|
|
rclIntersect.right = MIN(prclBounds->right, prcl->right);
|
|
rclIntersect.top = MAX(prclBounds->top, prcl->top);
|
|
rclIntersect.bottom = MAX(prclBounds->bottom, prcl->bottom);
|
|
|
|
*pcx = (rclIntersect.right - rclIntersect.left) > 0 ?
|
|
rclIntersect.right - rclIntersect.left : 0;
|
|
|
|
*pcy = (rclIntersect.bottom - rclIntersect.top) > 0 ?
|
|
rclIntersect.bottom - rclIntersect.top : 0 ;
|
|
}
|
|
else if (prcl)
|
|
{
|
|
*pcx = (prcl->right - prcl->left) > 0 ?
|
|
prcl->right - prcl->left : 0;
|
|
*pcy = (prcl->bottom - prcl->top) > 0 ?
|
|
prcl->bottom - prcl->top : 0;
|
|
}
|
|
else if (prclBounds)
|
|
{
|
|
*pcx = (prclBounds->right - prclBounds->left) > 0 ?
|
|
prclBounds->right - prclBounds->left : 0;
|
|
*pcy = (prclBounds->bottom - prclBounds->top) > 0 ?
|
|
prclBounds->bottom - prclBounds->top : 0;
|
|
|
|
}
|
|
}
|
|
|
|
return bRet;
|
|
}
|
|
|
|
__inline
|
|
BOOL bCheckDestSurfaceOverlap(SURFOBJ *pso, RECTL* prcl)
|
|
{
|
|
ERECTL ercl = *prcl;
|
|
|
|
// If we need to mirror do it.
|
|
if (ercl.bottom < ercl.top)
|
|
{
|
|
LONG lTemp = ercl.top;
|
|
ercl.top = ercl.bottom;
|
|
ercl.bottom = lTemp;
|
|
}
|
|
if (ercl.right < ercl.left)
|
|
{
|
|
LONG lTemp = ercl.left;
|
|
ercl.left = ercl.right;
|
|
ercl.right = lTemp;
|
|
}
|
|
|
|
ERECTL erclTrg(0, 0, pso->sizlBitmap.cx, pso->sizlBitmap.cy);
|
|
|
|
ercl *= erclTrg;
|
|
|
|
if (ercl.bEmpty())
|
|
return(FALSE);
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
__inline
|
|
BOOL bCheckSurfacePath(SURFOBJ *pso, PATHOBJ *ppo, CLIPOBJ *pco)
|
|
{
|
|
BOOL bRet = TRUE;
|
|
BOOL bTrivial;
|
|
RECTL *prcl;
|
|
|
|
if (pso && ppo)
|
|
{
|
|
if (pco)
|
|
{
|
|
bTrivial = (pco->iDComplexity == DC_TRIVIAL) ? TRUE : FALSE;
|
|
}
|
|
else
|
|
{
|
|
bTrivial = TRUE;
|
|
}
|
|
|
|
if (bTrivial)
|
|
{
|
|
//
|
|
// no clipping, check against ppo->rcfxBoundBox.
|
|
//
|
|
RECTFX rcfx;
|
|
|
|
rcfx = ((EPATHOBJ *)ppo)->ppath->rcfxBoundBox;
|
|
|
|
prcl = (RECTL *)&rcfx;
|
|
|
|
prcl->left = FXTOL(rcfx.xLeft);
|
|
prcl->top = FXTOL(rcfx.yTop);
|
|
prcl->right = FXTOL(rcfx.xRight);
|
|
prcl->bottom = FXTOL(rcfx.yBottom);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// there is clipping invloved, check against pco->rclBounds.
|
|
//
|
|
prcl = &(pco->rclBounds);
|
|
}
|
|
|
|
if (prcl)
|
|
{
|
|
if ((prcl->left > prcl->right) || (prcl->top > prcl->bottom))
|
|
{
|
|
WARNING ("prcl not well ordered, returing failure\n");
|
|
bRet = FALSE;
|
|
}
|
|
|
|
if (bRet && (prcl->right > pso->sizlBitmap.cx) || (prcl->left < 0) ||
|
|
(prcl->bottom > pso->sizlBitmap.cy)|| (prcl->top < 0))
|
|
{
|
|
bRet = FALSE;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
WARNING("bCheckSurfacePath either pso or ppo is NULL\n");
|
|
bRet = FALSE;
|
|
}
|
|
|
|
return bRet;
|
|
}
|
|
|
|
__inline
|
|
BOOL bCheckSurfacePoint(SURFOBJ *pso, POINTL *ptl)
|
|
{
|
|
BOOL bRet = TRUE;
|
|
|
|
if (pso && ptl)
|
|
{
|
|
if ((pso->sizlBitmap.cx < ptl->x) || (ptl->x < 0) ||
|
|
(pso->sizlBitmap.cy < ptl->y)|| (ptl->y < 0))
|
|
{
|
|
bRet = FALSE;
|
|
}
|
|
}
|
|
|
|
return bRet;
|
|
}
|
|
|
|
__inline
|
|
BOOL bCheckMask(SURFOBJ *psoMask, RECTL *prcl)
|
|
{
|
|
BOOL bRet = TRUE;
|
|
|
|
if (psoMask)
|
|
{
|
|
if (psoMask->iBitmapFormat != BMF_1BPP)
|
|
bRet = FALSE;
|
|
|
|
if (bRet)
|
|
bRet = bCheckSurfaceRect(psoMask, prcl, NULL);
|
|
}
|
|
|
|
return bRet;
|
|
}
|
|
|
|
//
|
|
// Make sure the we are not going to access pulXlate when there is no one
|
|
// Any other checks on xlateobj?
|
|
//
|
|
__inline
|
|
BOOL bCheckXlate(SURFOBJ *pso, XLATEOBJ *pxlo)
|
|
{
|
|
BOOL bRet = TRUE;
|
|
|
|
if (pso)
|
|
{
|
|
if (pxlo && !(pxlo->flXlate & XO_TRIVIAL))
|
|
{
|
|
switch (pso->iBitmapFormat)
|
|
{
|
|
case BMF_1BPP:
|
|
{
|
|
bRet = (pxlo->cEntries == 2) ? TRUE : FALSE;
|
|
break;
|
|
}
|
|
|
|
case BMF_4BPP:
|
|
{
|
|
//we can have a halftone palette of 8 entries
|
|
bRet = ((pxlo->cEntries == 16) || (pxlo->cEntries == 8)) ? TRUE : FALSE;
|
|
break;
|
|
}
|
|
|
|
case BMF_8BPP:
|
|
{
|
|
// halftone palette can be any combination
|
|
bRet = (pxlo->cEntries <= 256) ? TRUE : FALSE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return bRet;
|
|
}
|
|
|
|
|
|
__inline
|
|
PRECTL pRect(POINTL *pptl, RECTL *prcl, ULONG cx, ULONG cy)
|
|
{
|
|
PRECTL prclRet;
|
|
|
|
if (pptl)
|
|
{
|
|
prcl->left = pptl->x;
|
|
prcl->right = pptl->x + cx;
|
|
prcl->top = pptl->y;
|
|
prcl->bottom = pptl->y + cy;
|
|
prclRet = prcl;
|
|
}
|
|
else
|
|
{
|
|
prclRet = NULL;
|
|
}
|
|
|
|
return prclRet;
|
|
}
|
|
|
|
|
|
//
|
|
// check the order of a rectangle
|
|
//
|
|
__inline
|
|
BOOL bCheckRect(RECTL *prcl)
|
|
{
|
|
BOOL bRet = TRUE;
|
|
|
|
if (prcl)
|
|
{
|
|
if ((prcl->left > prcl->right) || (prcl->top > prcl->bottom))
|
|
{
|
|
WARNING ("prcl not well ordered, returing failure\n");
|
|
bRet = FALSE;
|
|
}
|
|
}
|
|
|
|
return bRet;
|
|
}
|
|
|
|
//
|
|
// Validate an HSURF and make sure it refers to a UMPD surface
|
|
//
|
|
|
|
__inline BOOL
|
|
ValidUmpdHsurf(
|
|
HSURF hsurf
|
|
)
|
|
|
|
{
|
|
SURFREF so(hsurf);
|
|
|
|
//
|
|
// Make sure hsurf is valid and it refers to a UMPD surface
|
|
//
|
|
|
|
return (so.bValid() && so.ps->bUMPD());
|
|
}
|
|
|
|
//
|
|
// Validate an HSURF and Unsecure hSecure
|
|
//
|
|
|
|
__inline BOOL
|
|
ValidUmpdHsurfAndUnSecure(
|
|
HSURF hsurf
|
|
)
|
|
|
|
{
|
|
SURFREF so(hsurf);
|
|
|
|
//
|
|
// Make sure hsurf is valid and it refers to a UMPD surface
|
|
//
|
|
|
|
if (so.bValid() && so.ps->bUMPD())
|
|
{
|
|
if (so.ps->hSecureUMPD)
|
|
{
|
|
ASSERTGDI(so.ps->iType() == STYPE_BITMAP, "surf type != STYPE_BITMAP\n");
|
|
MmUnsecureVirtualMemory(so.ps->hSecureUMPD);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
else
|
|
{
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// Validate an HDEV belongs to us
|
|
//
|
|
|
|
BOOL
|
|
ValidUmpdHdev(
|
|
HDEV hdev
|
|
)
|
|
{
|
|
BOOL bRet = FALSE;
|
|
|
|
if (hdev == NULL)
|
|
return FALSE;
|
|
|
|
if (!IS_SYSTEM_ADDRESS(hdev))
|
|
return FALSE;
|
|
|
|
PPDEV ppdev;
|
|
|
|
GreAcquireSemaphoreEx(ghsemDriverMgmt, SEMORDER_DRIVERMGMT, NULL);
|
|
|
|
for (ppdev = gppdevList; ppdev != NULL; ppdev = ppdev->ppdevNext)
|
|
{
|
|
if ((HDEV)ppdev == hdev)
|
|
{
|
|
bRet = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
GreReleaseSemaphoreEx(ghsemDriverMgmt);
|
|
|
|
return bRet;
|
|
}
|
|
|
|
//
|
|
// Make sure for each HOOK_XXX flag set, we actually
|
|
// has the driver function in ppfn
|
|
//
|
|
|
|
BOOL
|
|
ValidUmpdHooks (
|
|
HDEV hdev,
|
|
FLONG flHooks
|
|
)
|
|
{
|
|
PDEVOBJ po(hdev);
|
|
|
|
return (PPFNGET(po, BitBlt, flHooks) &&
|
|
PPFNGET(po, StretchBlt, flHooks) &&
|
|
PPFNGET(po, PlgBlt, flHooks) &&
|
|
PPFNGET(po, TextOut, flHooks) &&
|
|
PPFNGET(po, StrokePath, flHooks) &&
|
|
PPFNGET(po, FillPath, flHooks) &&
|
|
PPFNGET(po, StrokeAndFillPath, flHooks) &&
|
|
PPFNGET(po, Paint, flHooks) &&
|
|
PPFNGET(po, CopyBits, flHooks) &&
|
|
PPFNGET(po, LineTo, flHooks) &&
|
|
PPFNGET(po, StretchBltROP, flHooks) &&
|
|
PPFNGET(po, TransparentBlt, flHooks) &&
|
|
PPFNGET(po, AlphaBlend, flHooks) &&
|
|
PPFNGET(po, GradientFill, flHooks));
|
|
}
|
|
|
|
|
|
//
|
|
// Valid size for bitmap/surface creation
|
|
//
|
|
|
|
BOOL
|
|
ValidUmpdSizl(
|
|
SIZEL sizl
|
|
)
|
|
{
|
|
if ((sizl.cx <= 0) || (sizl.cy <= 0))
|
|
{
|
|
WARNING("ValidUmpdSizl failed - cx or cy <=0 \n");
|
|
return FALSE;
|
|
}
|
|
else
|
|
{
|
|
ULONGLONG cj = ((ULONGLONG)sizl.cx) * sizl.cy;
|
|
|
|
if (cj > MAXULONG)
|
|
{
|
|
WARNING("ValidUmpdSizl failed - cx*cy overflow\n");
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
ULONG
|
|
ValidUmpdOverflow(LONG cx, LONG cy)
|
|
{
|
|
ULONGLONG cj = ((ULONGLONG)cx) * cy;
|
|
|
|
if (cj > MAXULONG)
|
|
return FALSE;
|
|
else
|
|
return (ULONG)cj;
|
|
|
|
}
|
|
|
|
BOOL APIENTRY NtGdiEngAssociateSurface(
|
|
IN HSURF hsurf,
|
|
IN HDEV hdev,
|
|
IN FLONG flHooks
|
|
)
|
|
{
|
|
return ValidUmpdHsurf(hsurf) &&
|
|
ValidUmpdHdev(hdev) &&
|
|
(!(flHooks & ~HOOK_FLAGS))&&
|
|
ValidUmpdHooks (hdev, flHooks) &&
|
|
EngAssociateSurface(hsurf, hdev, flHooks);
|
|
}
|
|
|
|
BOOL APIENTRY NtGdiEngDeleteSurface(
|
|
IN HSURF hsurf
|
|
)
|
|
{
|
|
return ValidUmpdHsurfAndUnSecure(hsurf) &&
|
|
EngDeleteSurface(hsurf);
|
|
}
|
|
|
|
|
|
BOOL APIENTRY NtGdiEngMarkBandingSurface(
|
|
HSURF hsurf
|
|
)
|
|
{
|
|
return ValidUmpdHsurf(hsurf) &&
|
|
EngMarkBandingSurface(hsurf);
|
|
}
|
|
|
|
|
|
HBITMAP APIENTRY NtGdiEngCreateBitmap(
|
|
IN SIZEL sizl,
|
|
IN LONG lWidth,
|
|
IN ULONG iFormat,
|
|
IN FLONG fl,
|
|
IN PVOID pvBits
|
|
)
|
|
{
|
|
HBITMAP hbm = NULL;
|
|
HANDLE hSecure = NULL;
|
|
ULONG cj;
|
|
BOOL bSuccess = TRUE;
|
|
|
|
TRACE_INIT (("Entering NtGdiEngCreateBitmap\n"));
|
|
|
|
// check sizl.x and y
|
|
if (!ValidUmpdSizl(sizl))
|
|
return 0;
|
|
|
|
cj = ValidUmpdOverflow(lWidth, sizl.cy);
|
|
|
|
//
|
|
// set the high bit of iFormat to indicate umpd driver
|
|
//
|
|
iFormat |= UMPD_FLAG;
|
|
|
|
if (pvBits)
|
|
{
|
|
fl &= ~BMF_USERMEM;
|
|
__try
|
|
{
|
|
ProbeForRead(pvBits,cj,sizeof(BYTE));
|
|
hSecure = MmSecureVirtualMemory(pvBits, cj, PAGE_READWRITE);
|
|
|
|
if (!hSecure)
|
|
bSuccess = FALSE;
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
WARNING ("EngCreateBitmap -- exception in try/except \n");
|
|
bSuccess = FALSE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
fl |= BMF_USERMEM;
|
|
#if defined(_WIN64)
|
|
// wow64 printing
|
|
|
|
PW32THREAD pw32thread = W32GetCurrentThread();
|
|
|
|
if (pw32thread->pClientID)
|
|
fl |= BMF_UMPDMEM;
|
|
#endif
|
|
}
|
|
|
|
if (bSuccess)
|
|
{
|
|
hbm = EngCreateBitmap(sizl, lWidth, iFormat, fl, pvBits);
|
|
}
|
|
|
|
if (hSecure != NULL)
|
|
{
|
|
if (hbm != NULL)
|
|
{
|
|
//
|
|
// set hSecure into hSecureUMPD, at EngDeleteSurface time,
|
|
// we unsecure it
|
|
//
|
|
|
|
SURFREF so((HSURF) hbm);
|
|
|
|
if (so.bValid())
|
|
{
|
|
so.ps->hSecureUMPD = hSecure;
|
|
}
|
|
else
|
|
{
|
|
MmUnsecureVirtualMemory(hSecure);
|
|
|
|
EngDeleteSurface((HSURF)hbm);
|
|
|
|
hbm = NULL;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// We secured caller's memory but EngCreateBitmap failed.
|
|
//
|
|
|
|
MmUnsecureVirtualMemory(hSecure);
|
|
}
|
|
}
|
|
|
|
return (hbm);
|
|
}
|
|
|
|
BOOL APIENTRY NtGdiEngCopyBits(
|
|
IN SURFOBJ *psoDst,
|
|
OUT SURFOBJ *psoSrc,
|
|
IN CLIPOBJ *pco,
|
|
IN XLATEOBJ *pxlo,
|
|
IN RECTL *prclDst,
|
|
IN POINTL *pptlSrc
|
|
)
|
|
{
|
|
RECTL rcl;
|
|
POINTL ptl;
|
|
ULONG cx, cy;
|
|
BOOL bRet = TRUE;
|
|
|
|
EXTRACT_THREAD_UMPDOBJS(FALSE);
|
|
|
|
UMPDSURFOBJ umsoDst(psoDst, pUMObjs);
|
|
UMPDSURFOBJ umsoSrc(psoSrc, pUMObjs);
|
|
|
|
psoDst = umsoDst.pso();
|
|
psoSrc = umsoSrc.pso();
|
|
|
|
if (psoDst && psoSrc && (psoDst->iType == STYPE_BITMAP) && prclDst && pptlSrc)
|
|
{
|
|
__try
|
|
{
|
|
CaptureRECTL(&prclDst, &rcl);
|
|
CapturePOINTL(&pptlSrc, &ptl);
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
WARNING ("NtGdiEngCopyBits failed in try/except\n");
|
|
bRet = FALSE;
|
|
}
|
|
|
|
if (bRet && bOrder(prclDst))
|
|
{
|
|
pco = pUMObjs->GetDDIOBJ(pco, &psoDst->sizlBitmap);
|
|
pxlo = pUMObjs->GetDDIOBJ(pxlo);
|
|
|
|
if (bRet = (bCheckSurfaceRectSize(psoDst, prclDst, pco, &cx, &cy) && bCheckXlate(psoSrc, pxlo)))
|
|
{
|
|
RECTL rclSrc, *prclSrc;
|
|
|
|
prclSrc = psoSrc ? pRect(pptlSrc, &rclSrc, cx, cy) : NULL;
|
|
|
|
if (bRet = bCheckSurfaceRect(psoSrc, prclSrc, NULL))
|
|
{
|
|
bRet = EngCopyBits(psoDst,
|
|
psoSrc,
|
|
pco,
|
|
pxlo,
|
|
prclDst,
|
|
pptlSrc);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
bRet = FALSE;
|
|
}
|
|
|
|
FIXUP_THREAD_UMPDOBJS;
|
|
return (bRet);
|
|
}
|
|
|
|
BOOL APIENTRY NtGdiEngStretchBlt(
|
|
SURFOBJ *psoDest,
|
|
SURFOBJ *psoSrc,
|
|
SURFOBJ *psoMask,
|
|
CLIPOBJ *pco,
|
|
XLATEOBJ *pxlo,
|
|
COLORADJUSTMENT *pca,
|
|
POINTL *pptlHTOrg,
|
|
RECTL *prclDest,
|
|
RECTL *prclSrc,
|
|
POINTL *pptlMask,
|
|
ULONG iMode
|
|
)
|
|
{
|
|
BOOL bRet = TRUE;
|
|
RECTL rclDst, rclSrc;
|
|
POINTL ptlMask, ptlHTOrg;
|
|
COLORADJUSTMENT ca;
|
|
|
|
EXTRACT_THREAD_UMPDOBJS(FALSE);
|
|
|
|
UMPDSURFOBJ umsoDest(psoDest, pUMObjs);
|
|
UMPDSURFOBJ umsoSrc(psoSrc, pUMObjs);
|
|
UMPDSURFOBJ umsoMask(psoMask, pUMObjs);
|
|
|
|
psoDest = umsoDest.pso();
|
|
psoSrc = umsoSrc.pso();
|
|
psoMask = umsoMask.pso();
|
|
|
|
if (!pptlHTOrg && (iMode == HALFTONE))
|
|
{
|
|
WARNING ("pptlHTOrg is NULL for HALFTONE mode\n");
|
|
FIXUP_THREAD_UMPDOBJS;
|
|
return (FALSE);
|
|
}
|
|
|
|
if (psoDest && psoSrc && prclDest && prclSrc)
|
|
{
|
|
__try
|
|
{
|
|
CaptureRECTL(&prclDest, &rclDst);
|
|
CapturePOINTL(&pptlMask, &ptlMask);
|
|
CaptureRECTL(&prclSrc, &rclSrc);
|
|
CaptureCOLORADJUSTMENT(&pca, &ca);
|
|
CapturePOINTL(&pptlHTOrg, &ptlHTOrg);
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
WARNING ("NtGdiEngStretchBlt failed in try/except\n");
|
|
bRet = FALSE;
|
|
}
|
|
|
|
if (!bCheckDestSurfaceOverlap(psoDest,prclDest))
|
|
{
|
|
FIXUP_THREAD_UMPDOBJS;
|
|
return(TRUE);
|
|
}
|
|
|
|
if (bRet)
|
|
{
|
|
pco = pUMObjs->GetDDIOBJ(pco, &psoDest->sizlBitmap);
|
|
pxlo = pUMObjs->GetDDIOBJ(pxlo);
|
|
|
|
//
|
|
// EngStretchBlt does trimming and checking of the dest and src rectangles,
|
|
// but it assumes the src rect is well-ordered. Check here.
|
|
//
|
|
bRet = bOrder(prclSrc) && bCheckXlate(psoSrc, pxlo);
|
|
|
|
if (bRet && psoMask)
|
|
{
|
|
RECTL rclMask, *prclMask;
|
|
|
|
ULONG cx, cy;
|
|
|
|
if (bRet = bCheckSurfaceRectSize(psoSrc, prclSrc, NULL, &cx, &cy))
|
|
{
|
|
prclMask = pRect(pptlMask, &rclMask, cx, cy);
|
|
bRet = bCheckMask(psoMask, prclMask);
|
|
}
|
|
}
|
|
|
|
if (bRet)
|
|
bRet = EngStretchBlt(psoDest,
|
|
psoSrc,
|
|
psoMask,
|
|
pco,
|
|
pxlo,
|
|
pca,
|
|
pptlHTOrg,
|
|
prclDest,
|
|
prclSrc,
|
|
pptlMask,
|
|
iMode);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
bRet = FALSE;
|
|
}
|
|
|
|
FIXUP_THREAD_UMPDOBJS;
|
|
return (bRet);
|
|
|
|
}
|
|
|
|
BOOL APIENTRY NtGdiEngStretchBltROP(
|
|
SURFOBJ *psoDest,
|
|
SURFOBJ *psoSrc,
|
|
SURFOBJ *psoMask,
|
|
CLIPOBJ *pco,
|
|
XLATEOBJ *pxlo,
|
|
COLORADJUSTMENT *pca,
|
|
POINTL *pptlHTOrg,
|
|
RECTL *prclDest,
|
|
RECTL *prclSrc,
|
|
POINTL *pptlMask,
|
|
ULONG iMode,
|
|
BRUSHOBJ *pbo,
|
|
DWORD rop4
|
|
)
|
|
{
|
|
BOOL bRet = TRUE;
|
|
RECTL rclDst, rclSrc;
|
|
POINTL ptlMask, ptlHTOrg;
|
|
COLORADJUSTMENT ca;
|
|
|
|
EXTRACT_THREAD_UMPDOBJS(FALSE);
|
|
|
|
UMPDSURFOBJ umsoDest(psoDest, pUMObjs);
|
|
UMPDSURFOBJ umsoSrc(psoSrc, pUMObjs);
|
|
UMPDSURFOBJ umsoMask(psoMask, pUMObjs);
|
|
|
|
psoDest = umsoDest.pso();
|
|
psoSrc = umsoSrc.pso();
|
|
psoMask = umsoMask.pso();
|
|
|
|
if (!pptlHTOrg && (iMode == HALFTONE))
|
|
{
|
|
WARNING ("pptlHTOrg is NULL for HALFTONE mode\n");
|
|
FIXUP_THREAD_UMPDOBJS;
|
|
return (FALSE);
|
|
}
|
|
|
|
if (psoDest && psoSrc && prclDest && prclSrc)
|
|
{
|
|
__try
|
|
{
|
|
CaptureRECTL(&prclDest, &rclDst);
|
|
CaptureRECTL(&prclSrc, &rclSrc);
|
|
CapturePOINTL(&pptlMask, &ptlMask);
|
|
CapturePOINTL(&pptlHTOrg, &ptlHTOrg);
|
|
CaptureCOLORADJUSTMENT(&pca, &ca);
|
|
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
WARNING ("NtGdiEngStretchBltTROP failed in try/except\n");
|
|
bRet = FALSE;
|
|
}
|
|
|
|
if (!bCheckDestSurfaceOverlap(psoDest,prclDest))
|
|
{
|
|
FIXUP_THREAD_UMPDOBJS;
|
|
return(TRUE);
|
|
}
|
|
|
|
if (bRet)
|
|
{
|
|
ULONG cx, cy;
|
|
BRUSHOBJ boTemp;
|
|
|
|
pco = pUMObjs->GetDDIOBJ(pco, &psoDest->sizlBitmap);
|
|
pxlo = pUMObjs->GetDDIOBJ(pxlo);
|
|
|
|
//
|
|
// EngStretchBlt does trimming and checking of the rectangles,
|
|
// but it assumes the src rect is well-ordered, check here.
|
|
//
|
|
|
|
bRet = (!ROP4NEEDSRC(rop4) || bOrder(prclSrc)) && bCheckXlate(psoSrc, pxlo) &&
|
|
(!ROP4NEEDMASK(rop4) || psoMask || PROBEDISPATBRUSH(pbo));
|
|
|
|
if (ROP4NEEDMASK(rop4) && (!psoMask || !pptlMask))
|
|
bRet = FALSE;
|
|
if (bRet && (rop4 == 0XAACC) && psoMask)
|
|
{
|
|
RECTL rclMask, *prclMask;
|
|
|
|
ULONG cx, cy;
|
|
|
|
if (bRet = bCheckSurfaceRectSize(psoSrc, prclSrc, NULL, &cx, &cy))
|
|
{
|
|
prclMask = pRect(pptlMask, &rclMask, cx, cy);
|
|
bRet = bCheckMask(psoMask, prclMask);
|
|
}
|
|
}
|
|
|
|
MAP_UM_BRUSHOBJ(pUMObjs, pbo, &boTemp);
|
|
|
|
bRet = bRet &&
|
|
EngStretchBltROP(psoDest,
|
|
psoSrc,
|
|
psoMask,
|
|
pco,
|
|
pxlo,
|
|
pca,
|
|
pptlHTOrg,
|
|
prclDest,
|
|
prclSrc,
|
|
pptlMask,
|
|
iMode,
|
|
pbo,
|
|
rop4);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
bRet = FALSE;
|
|
}
|
|
|
|
FIXUP_THREAD_UMPDOBJS;
|
|
return (bRet);
|
|
}
|
|
|
|
BOOL APIENTRY NtGdiEngPlgBlt(
|
|
SURFOBJ *psoTrg,
|
|
SURFOBJ *psoSrc,
|
|
SURFOBJ *psoMsk,
|
|
CLIPOBJ *pco,
|
|
XLATEOBJ *pxlo,
|
|
COLORADJUSTMENT *pca,
|
|
POINTL *pptlBrushOrg,
|
|
POINTFIX *pptfxDest,
|
|
RECTL *prclSrc,
|
|
POINTL *pptlMask,
|
|
ULONG iMode
|
|
)
|
|
{
|
|
BOOL bRet = TRUE;
|
|
RECTL rcl;
|
|
POINTL ptl, ptlBrushOrg;
|
|
POINTFIX pptfx[3];
|
|
COLORADJUSTMENT ca;
|
|
|
|
EXTRACT_THREAD_UMPDOBJS(FALSE);
|
|
|
|
UMPDSURFOBJ umsoTrg(psoTrg, pUMObjs);
|
|
UMPDSURFOBJ umsoSrc(psoSrc, pUMObjs);
|
|
UMPDSURFOBJ umsoMsk(psoMsk, pUMObjs);
|
|
|
|
psoTrg = umsoTrg.pso();
|
|
psoSrc = umsoSrc.pso();
|
|
psoMsk = umsoMsk.pso();
|
|
|
|
if (psoTrg && psoSrc && prclSrc && pptfxDest)
|
|
{
|
|
__try
|
|
{
|
|
CaptureRECTL(&prclSrc, &rcl);
|
|
CaptureCOLORADJUSTMENT(&pca, &ca);
|
|
CapturePOINTL(&pptlMask, &ptl);
|
|
CapturePOINTL(&pptlBrushOrg, &ptlBrushOrg);
|
|
CaptureBits(pptfx, pptfxDest, sizeof(POINTFIX)*3);
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
WARNING ("NtGdiEngPlgBlt failed in try/except\n");
|
|
bRet = FALSE;
|
|
}
|
|
|
|
if (bRet)
|
|
{
|
|
ULONG cx, cy;
|
|
|
|
pco = pUMObjs->GetDDIOBJ(pco, &psoTrg->sizlBitmap);
|
|
pxlo = pUMObjs->GetDDIOBJ(pxlo);
|
|
|
|
//
|
|
// EngPlgBlt does the rectangle trimming and checking of dest and src
|
|
//
|
|
|
|
if (bRet = (bCheckRect(prclSrc) && bCheckXlate(psoSrc, pxlo)))
|
|
{
|
|
if (psoMsk)
|
|
{
|
|
RECTL rclMask, *prclMask;
|
|
|
|
ULONG cx, cy;
|
|
|
|
if (bRet = bCheckSurfaceRectSize(psoSrc, prclSrc, NULL, &cx, &cy))
|
|
{
|
|
prclMask = pRect(pptlMask, &rclMask, cx, cy);
|
|
bRet = bCheckMask(psoMsk, prclMask);
|
|
}
|
|
}
|
|
|
|
if (bRet)
|
|
bRet = EngPlgBlt(psoTrg,
|
|
psoSrc,
|
|
psoMsk,
|
|
pco,
|
|
pxlo,
|
|
pca,
|
|
&ptlBrushOrg,
|
|
pptfx,
|
|
prclSrc,
|
|
pptlMask,
|
|
iMode);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
bRet = FALSE;
|
|
}
|
|
|
|
FIXUP_THREAD_UMPDOBJS;
|
|
return (bRet);
|
|
}
|
|
|
|
SURFOBJ *APIENTRY NtGdiEngLockSurface(
|
|
IN HSURF hsurf
|
|
)
|
|
{
|
|
EXTRACT_THREAD_UMPDOBJS(NULL);
|
|
|
|
SURFOBJ *surfRet = pUMObjs->LockSurface(hsurf);
|
|
|
|
FIXUP_THREAD_UMPDOBJS;
|
|
|
|
return (surfRet);
|
|
}
|
|
|
|
VOID APIENTRY NtGdiEngUnlockSurface(
|
|
IN SURFOBJ *pso
|
|
)
|
|
{
|
|
EXTRACT_THREAD_UMPDOBJS;
|
|
|
|
pUMObjs->UnlockSurface(pso);
|
|
|
|
FIXUP_THREAD_UMPDOBJS;
|
|
}
|
|
|
|
BOOL APIENTRY NtGdiEngBitBlt(
|
|
IN SURFOBJ *psoDst,
|
|
IN SURFOBJ *psoSrc,
|
|
IN SURFOBJ *psoMask,
|
|
IN CLIPOBJ *pco,
|
|
IN XLATEOBJ *pxlo,
|
|
IN RECTL *prclDst,
|
|
IN POINTL *pptlSrc,
|
|
IN POINTL *pptlMask,
|
|
IN BRUSHOBJ *pbo,
|
|
IN POINTL *pptlBrush,
|
|
IN ROP4 rop4
|
|
)
|
|
{
|
|
BOOL bRet = TRUE;
|
|
RECTL rclDst;
|
|
POINTL ptlSrc, ptlMask, ptlBrush;
|
|
BRUSHOBJ boTemp;
|
|
|
|
TRACE_INIT (("Entering NtGdiEngBitBlt\n"));
|
|
|
|
EXTRACT_THREAD_UMPDOBJS(FALSE);
|
|
|
|
UMPDSURFOBJ umsoDst(psoDst, pUMObjs);
|
|
UMPDSURFOBJ umsoSrc(psoSrc, pUMObjs);
|
|
UMPDSURFOBJ umsoMask(psoMask, pUMObjs);
|
|
|
|
psoDst = umsoDst.pso();
|
|
psoSrc = umsoSrc.pso();
|
|
psoMask = umsoMask.pso();
|
|
|
|
MAP_UM_BRUSHOBJ(pUMObjs, pbo, &boTemp);
|
|
pxlo = pUMObjs->GetDDIOBJ(pxlo);
|
|
|
|
if (((rop4 & 0xffff0000) != 0) ||
|
|
!prclDst ||
|
|
(ROP4NEEDPAT(rop4) && (!pbo || ISPATBRUSH(pbo) && !pptlBrush)) ||
|
|
(ROP4NEEDSRC(rop4) && !(pptlSrc && psoSrc)) ||
|
|
(ROP4NEEDMASK(rop4) && !(psoMask || ISPATBRUSH(pbo))))
|
|
{
|
|
WARNING ("NtGdiEngBitBlt invalid parameters passed in\n");
|
|
FIXUP_THREAD_UMPDOBJS;
|
|
return FALSE;
|
|
}
|
|
|
|
if (psoDst)
|
|
{
|
|
__try
|
|
{
|
|
CaptureRECTL(&prclDst, &rclDst);
|
|
CapturePOINTL(&pptlSrc, &ptlSrc);
|
|
CapturePOINTL(&pptlMask, &ptlMask);
|
|
CapturePOINTL(&pptlBrush, &ptlBrush);
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
WARNING ("NtGdiEngBitBlt failed in try/except\n");
|
|
bRet = FALSE;
|
|
}
|
|
|
|
if (bRet)
|
|
{
|
|
ULONG cx, cy;
|
|
|
|
pco = pUMObjs->GetDDIOBJ(pco, &psoDst->sizlBitmap);
|
|
|
|
if (bRet = bCheckSurfaceRectSize(psoDst, prclDst, pco, &cx, &cy) &&
|
|
bCheckXlate(psoSrc, pxlo))
|
|
{
|
|
RECTL rclSrc, *prclSrc;
|
|
RECTL rclMask, *prclMask;
|
|
|
|
prclSrc = psoSrc ? pRect(pptlSrc, &rclSrc, cx, cy) : NULL;
|
|
prclMask = psoMask ? pRect(pptlMask, &rclMask, cx, cy) : NULL;
|
|
|
|
if (bRet = (bCheckSurfaceRect(psoSrc, prclSrc, NULL) &&
|
|
bCheckMask(psoMask, prclMask)))
|
|
{
|
|
bRet = EngBitBlt(psoDst,
|
|
psoSrc,
|
|
psoMask,
|
|
pco,
|
|
pxlo,
|
|
prclDst,
|
|
pptlSrc,
|
|
pptlMask,
|
|
pbo,
|
|
pptlBrush,
|
|
rop4);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
bRet = FALSE;
|
|
|
|
FIXUP_THREAD_UMPDOBJS;
|
|
return (bRet);
|
|
}
|
|
|
|
|
|
BOOL APIENTRY NtGdiEngStrokePath(
|
|
SURFOBJ *pso,
|
|
PATHOBJ *ppo,
|
|
CLIPOBJ *pco,
|
|
XFORMOBJ *pxo,
|
|
BRUSHOBJ *pbo,
|
|
POINTL *pptlBrushOrg,
|
|
LINEATTRS *plineattrs,
|
|
MIX mix
|
|
)
|
|
{
|
|
BOOL bRet = TRUE;
|
|
POINTL ptl;
|
|
LINEATTRS line;
|
|
BRUSHOBJ boTemp;
|
|
|
|
EXTRACT_THREAD_UMPDOBJS(FALSE);
|
|
|
|
TRACE_INIT (("Entering NtGdiEngStrokePath\n"));
|
|
|
|
UMPDSURFOBJ umso(pso, pUMObjs);
|
|
|
|
pso = umso.pso();
|
|
ppo = pUMObjs->GetDDIOBJ(ppo);
|
|
|
|
MAP_UM_BRUSHOBJ(pUMObjs, pbo, &boTemp);
|
|
|
|
if (pso && pbo && ppo && plineattrs && pptlBrushOrg)
|
|
{
|
|
__try
|
|
{
|
|
CapturePOINTL(&pptlBrushOrg, &ptl);
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
WARNING ("NtGdiEngStrokePath failed in try/except\n");
|
|
bRet = FALSE;
|
|
}
|
|
|
|
if (bRet)
|
|
bRet = bCaptureLINEATTRS(&plineattrs, &line);
|
|
|
|
if (bRet)
|
|
{
|
|
pco = pUMObjs->GetDDIOBJ(pco, &pso->sizlBitmap);
|
|
pxo = pUMObjs->GetDDIOBJ(pxo);
|
|
if ((plineattrs->fl & LA_GEOMETRIC) && pxo == 0)
|
|
bRet = FALSE;
|
|
|
|
bRet = bRet && bCheckSurfacePath(pso, ppo, pco) &&
|
|
(!MIXNEEDMASK(mix) || ISPATBRUSH(pbo)) &&
|
|
EngStrokePath(pso,
|
|
ppo,
|
|
pco,
|
|
pxo,
|
|
pbo,
|
|
pptlBrushOrg,
|
|
plineattrs,
|
|
mix);
|
|
|
|
if (plineattrs && plineattrs->pstyle)
|
|
VFREEMEM(plineattrs->pstyle);
|
|
}
|
|
}
|
|
else
|
|
bRet = FALSE;
|
|
|
|
FIXUP_THREAD_UMPDOBJS;
|
|
return (bRet);
|
|
}
|
|
|
|
|
|
BOOL APIENTRY NtGdiEngFillPath(
|
|
SURFOBJ *pso,
|
|
PATHOBJ *ppo,
|
|
CLIPOBJ *pco,
|
|
BRUSHOBJ *pbo,
|
|
POINTL *pptlBrushOrg,
|
|
MIX mix,
|
|
FLONG flOptions
|
|
)
|
|
{
|
|
BOOL bRet = FALSE;
|
|
POINTL ptlBrushOrg;
|
|
BRUSHOBJ boTemp;
|
|
|
|
EXTRACT_THREAD_UMPDOBJS(FALSE);
|
|
|
|
UMPDSURFOBJ umso(pso, pUMObjs);
|
|
|
|
pso = umso.pso();
|
|
ppo = pUMObjs->GetDDIOBJ(ppo);
|
|
pco = pso ? pUMObjs->GetDDIOBJ(pco, &pso->sizlBitmap) : NULL;
|
|
|
|
MAP_UM_BRUSHOBJ(pUMObjs, pbo, &boTemp);
|
|
|
|
if (pso && pbo && ppo && pco && (pco->iMode == TC_RECTANGLES) && pptlBrushOrg)
|
|
{
|
|
__try
|
|
{
|
|
CapturePOINTL(&pptlBrushOrg, &ptlBrushOrg);
|
|
bRet = TRUE;
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
WARNING ("NtGdiEngFillPath failed in try/except\n");
|
|
}
|
|
|
|
bRet = bRet &&
|
|
bCheckSurfacePath(pso, ppo, pco) &&
|
|
(!MIXNEEDMASK(mix) || ISPATBRUSH(pbo)) &&
|
|
EngFillPath(pso,
|
|
ppo,
|
|
pco,
|
|
pbo,
|
|
pptlBrushOrg,
|
|
mix,
|
|
flOptions);
|
|
}
|
|
|
|
FIXUP_THREAD_UMPDOBJS;
|
|
return (bRet);
|
|
}
|
|
|
|
|
|
BOOL APIENTRY NtGdiEngStrokeAndFillPath(
|
|
SURFOBJ *pso,
|
|
PATHOBJ *ppo,
|
|
CLIPOBJ *pco,
|
|
XFORMOBJ *pxo,
|
|
BRUSHOBJ *pboStroke,
|
|
LINEATTRS *plineattrs,
|
|
BRUSHOBJ *pboFill,
|
|
POINTL *pptlBrushOrg,
|
|
MIX mixFill,
|
|
FLONG flOptions
|
|
)
|
|
{
|
|
BOOL bRet = FALSE;
|
|
POINTL ptl;
|
|
LINEATTRS line;
|
|
BRUSHOBJ boTempStroke, boTempFill;
|
|
|
|
EXTRACT_THREAD_UMPDOBJS(FALSE);
|
|
|
|
UMPDSURFOBJ umso(pso, pUMObjs);
|
|
|
|
pso = umso.pso();
|
|
ppo = pUMObjs->GetDDIOBJ(ppo);
|
|
pco = pso ? pUMObjs->GetDDIOBJ(pco, &pso->sizlBitmap) : NULL;
|
|
|
|
MAP_UM_BRUSHOBJ(pUMObjs, pboStroke, &boTempStroke);
|
|
MAP_UM_BRUSHOBJ(pUMObjs, pboFill, &boTempFill);
|
|
|
|
if (pso && pboStroke && pboFill && ppo && plineattrs && pco && pptlBrushOrg)
|
|
{
|
|
__try
|
|
{
|
|
CapturePOINTL(&pptlBrushOrg, &ptl);
|
|
bRet = TRUE;
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
WARNING ("NtGdiEngStrokeAndFillPath failed in try/except\n");
|
|
}
|
|
|
|
if (bRet)
|
|
bRet = bCaptureLINEATTRS(&plineattrs, &line);
|
|
|
|
if (bRet)
|
|
{
|
|
pxo = pUMObjs->GetDDIOBJ(pxo);
|
|
if ((plineattrs->fl & LA_GEOMETRIC) && pxo == 0)
|
|
bRet = FALSE;
|
|
|
|
bRet = bRet && bCheckSurfacePath(pso, ppo, pco) &&
|
|
(!MIXNEEDMASK(mixFill) || ISPATBRUSH(pboFill)) &&
|
|
EngStrokeAndFillPath(pso,
|
|
ppo,
|
|
pco,
|
|
pxo,
|
|
pboStroke,
|
|
plineattrs,
|
|
pboFill,
|
|
pptlBrushOrg,
|
|
mixFill,
|
|
flOptions);
|
|
|
|
if (plineattrs && plineattrs->pstyle)
|
|
VFREEMEM(plineattrs->pstyle);
|
|
}
|
|
}
|
|
|
|
FIXUP_THREAD_UMPDOBJS;
|
|
return bRet;
|
|
}
|
|
|
|
|
|
BOOL APIENTRY
|
|
NtGdiEngPaint(
|
|
SURFOBJ *pso,
|
|
CLIPOBJ *pco,
|
|
BRUSHOBJ *pbo,
|
|
POINTL *pptlBrushOrg,
|
|
MIX mix
|
|
)
|
|
{
|
|
POINTL ptlBrushOrg;
|
|
BOOL bRet = TRUE;
|
|
BRUSHOBJ boTemp;
|
|
|
|
EXTRACT_THREAD_UMPDOBJS(FALSE);
|
|
|
|
UMPDSURFOBJ umso(pso, pUMObjs);
|
|
|
|
pso = umso.pso();
|
|
pco = pso ? pUMObjs->GetDDIOBJ(pco, &pso->sizlBitmap) : NULL;
|
|
|
|
MAP_UM_BRUSHOBJ(pUMObjs, pbo, &boTemp);
|
|
|
|
if (pso && pco && (pco->iMode == TC_RECTANGLES) && (mix & 0xff00))
|
|
{
|
|
|
|
__try
|
|
{
|
|
CapturePOINTL(&pptlBrushOrg, &ptlBrushOrg);
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
WARNING ("NtGdiEngPaint failed in try/except\n");
|
|
bRet = FALSE;
|
|
}
|
|
|
|
if (bRet && (bRet = bCheckSurfaceRect(pso, NULL, pco)))
|
|
{
|
|
bRet = EngPaint(pso, pco, pbo, pptlBrushOrg, mix);
|
|
}
|
|
}
|
|
else
|
|
bRet = FALSE;
|
|
|
|
FIXUP_THREAD_UMPDOBJS;
|
|
return bRet;
|
|
}
|
|
|
|
|
|
BOOL APIENTRY NtGdiEngLineTo(
|
|
SURFOBJ *pso,
|
|
CLIPOBJ *pco,
|
|
BRUSHOBJ *pbo,
|
|
LONG x1,
|
|
LONG y1,
|
|
LONG x2,
|
|
LONG y2,
|
|
RECTL *prclBounds,
|
|
MIX mix
|
|
)
|
|
{
|
|
BOOL bRet = TRUE;
|
|
RECTL rcl;
|
|
RECTL rclline = {x1,y1,x2,y2};
|
|
BRUSHOBJ boTemp;
|
|
|
|
EXTRACT_THREAD_UMPDOBJS(FALSE);
|
|
|
|
UMPDSURFOBJ umso(pso, pUMObjs);
|
|
|
|
pso = umso.pso();
|
|
|
|
MAP_UM_BRUSHOBJ(pUMObjs, pbo, &boTemp);
|
|
|
|
if (pso && pbo)
|
|
{
|
|
__try
|
|
{
|
|
CaptureRECTL(&prclBounds, &rcl);
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
WARNING ("NtGdiEngLineTo failed in try/except\n");
|
|
bRet = FALSE;
|
|
}
|
|
|
|
if (bRet)
|
|
{
|
|
pco = pUMObjs->GetDDIOBJ(pco, &pso->sizlBitmap);
|
|
|
|
if (bRet = bCheckSurfaceRect(pso, &rclline, pco))
|
|
{
|
|
bRet = EngLineTo(pso,
|
|
pco,
|
|
pbo,
|
|
x1,
|
|
y1,
|
|
x2,
|
|
y2,
|
|
prclBounds,
|
|
mix);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
bRet = FALSE;
|
|
|
|
FIXUP_THREAD_UMPDOBJS;
|
|
return (bRet);
|
|
}
|
|
|
|
|
|
BOOL APIENTRY NtGdiEngAlphaBlend(
|
|
SURFOBJ *psoDest,
|
|
SURFOBJ *psoSrc,
|
|
CLIPOBJ *pco,
|
|
XLATEOBJ *pxlo,
|
|
RECTL *prclDest,
|
|
RECTL *prclSrc,
|
|
BLENDOBJ *pBlendObj
|
|
)
|
|
{
|
|
BOOL bRet = TRUE;
|
|
RECTL rclDest, rclSrc;
|
|
|
|
EXTRACT_THREAD_UMPDOBJS(FALSE);
|
|
|
|
UMPDSURFOBJ umsoDest(psoDest, pUMObjs);
|
|
UMPDSURFOBJ umsoSrc(psoSrc, pUMObjs);
|
|
|
|
pBlendObj = pUMObjs->GetDDIOBJ(pBlendObj);
|
|
|
|
psoDest = umsoDest.pso();
|
|
psoSrc = umsoSrc.pso();
|
|
|
|
if (psoDest && psoSrc && pBlendObj && prclDest && prclSrc)
|
|
{
|
|
__try
|
|
{
|
|
CaptureRECTL(&prclSrc, &rclSrc);
|
|
CaptureRECTL(&prclDest, &rclDest);
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
WARNING ("NtGdiEngAlphaBlend failed in try/except\n");
|
|
bRet = FALSE;
|
|
}
|
|
|
|
if (bRet && bOrder(prclSrc) && bOrder(prclDest))
|
|
{
|
|
pco = pUMObjs->GetDDIOBJ(pco, &psoDest->sizlBitmap);
|
|
pxlo = pUMObjs->GetDDIOBJ(pxlo);
|
|
|
|
if (bRet = (bCheckSurfaceRect(psoSrc, prclSrc, NULL) && bCheckXlate(psoSrc, pxlo)))
|
|
{
|
|
bRet = EngAlphaBlend(psoDest,
|
|
psoSrc,
|
|
pco,
|
|
pxlo,
|
|
prclDest,
|
|
prclSrc,
|
|
pBlendObj);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
bRet = FALSE;
|
|
|
|
FIXUP_THREAD_UMPDOBJS;
|
|
return (bRet);
|
|
}
|
|
|
|
//
|
|
// Make sure the Vertex and Mesh data are valid. i.e that they are bounded
|
|
// within each other.
|
|
//
|
|
|
|
__inline
|
|
BOOL bValidVertexMeshData(
|
|
TRIVERTEX *pVertex,
|
|
PVOID pMeshIn,
|
|
ULONG nVertex,
|
|
ULONG nMesh,
|
|
ULONG ulMode)
|
|
{
|
|
ULONG ulIndex;
|
|
|
|
if (nVertex <= 1)
|
|
return FALSE;
|
|
|
|
PTRIVERTEX pTVb = pVertex;
|
|
PTRIVERTEX pTVe = pVertex + nVertex - 1;
|
|
PTRIVERTEX pTV;
|
|
|
|
switch (ulMode)
|
|
{
|
|
case GRADIENT_FILL_RECT_H:
|
|
case GRADIENT_FILL_RECT_V:
|
|
{
|
|
PGRADIENT_RECT pMesh = (PGRADIENT_RECT)pMeshIn;
|
|
for (ulIndex = 0; ulIndex < nMesh; ulIndex++)
|
|
{
|
|
pTV = pTVb + pMesh[ulIndex].UpperLeft;
|
|
if (!(pTV >= pTVb && pTV <= pTVe))
|
|
return FALSE;
|
|
pTV = pTVb + pMesh[ulIndex].LowerRight;
|
|
if (!(pTV >= pTVb && pTV <= pTVe))
|
|
return FALSE;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case GRADIENT_FILL_TRIANGLE:
|
|
{
|
|
PGRADIENT_TRIANGLE pMesh = (PGRADIENT_TRIANGLE)pMeshIn;
|
|
for (ulIndex = 0; ulIndex < nMesh; ulIndex++)
|
|
{
|
|
pTV = pTVb + pMesh[ulIndex].Vertex1;
|
|
if (!(pTV >= pTVb && pTV <= pTVe))
|
|
return FALSE;
|
|
pTV = pTVb + pMesh[ulIndex].Vertex2;
|
|
if (!(pTV >= pTVb && pTV <= pTVe))
|
|
return FALSE;
|
|
pTV = pTVb + pMesh[ulIndex].Vertex3;
|
|
if (!(pTV >= pTVb && pTV <= pTVe))
|
|
return FALSE;
|
|
}
|
|
}
|
|
break;
|
|
|
|
default:
|
|
return FALSE;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL APIENTRY NtGdiEngGradientFill(
|
|
SURFOBJ *psoDest,
|
|
CLIPOBJ *pco,
|
|
XLATEOBJ *pxlo,
|
|
TRIVERTEX *pVertex,
|
|
ULONG nVertex,
|
|
PVOID pMesh,
|
|
ULONG nMesh,
|
|
RECTL *prclExtents,
|
|
POINTL *pptlDitherOrg,
|
|
ULONG ulMode
|
|
)
|
|
{
|
|
BOOL bRet = TRUE;
|
|
RECTL rcl;
|
|
POINTL ptl;
|
|
TRIVERTEX *pVertexTmp = (TRIVERTEX *)NULL;
|
|
PVOID pMeshTmp = NULL;
|
|
ULONG cjMesh;
|
|
|
|
EXTRACT_THREAD_UMPDOBJS(FALSE);
|
|
|
|
UMPDSURFOBJ umsoDest(psoDest, pUMObjs);
|
|
psoDest = umsoDest.pso();
|
|
|
|
switch (ulMode)
|
|
{
|
|
case GRADIENT_FILL_RECT_H:
|
|
case GRADIENT_FILL_RECT_V:
|
|
|
|
cjMesh = sizeof(GRADIENT_RECT);
|
|
|
|
if (BALLOC_OVERFLOW1(nMesh, GRADIENT_RECT))
|
|
{
|
|
FIXUP_THREAD_UMPDOBJS;
|
|
return FALSE;
|
|
}
|
|
|
|
break;
|
|
|
|
case GRADIENT_FILL_TRIANGLE:
|
|
|
|
cjMesh = sizeof(GRADIENT_TRIANGLE);
|
|
|
|
if (BALLOC_OVERFLOW1(nMesh, GRADIENT_TRIANGLE))
|
|
{
|
|
FIXUP_THREAD_UMPDOBJS;
|
|
return FALSE;
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
WARNING ("Invalid ulMode in DrvGradientFill\n");
|
|
FIXUP_THREAD_UMPDOBJS;
|
|
return FALSE;
|
|
}
|
|
|
|
if (nMesh == 0 || nVertex == 0)
|
|
{
|
|
FIXUP_THREAD_UMPDOBJS;
|
|
return TRUE;
|
|
}
|
|
|
|
cjMesh *= nMesh;
|
|
|
|
if (BALLOC_OVERFLOW1(nVertex, TRIVERTEX))
|
|
{
|
|
FIXUP_THREAD_UMPDOBJS;
|
|
return FALSE;
|
|
}
|
|
|
|
pVertexTmp = (TRIVERTEX *)PALLOCNOZ (sizeof(TRIVERTEX)*nVertex, UMPD_MEMORY_TAG);
|
|
|
|
pMeshTmp = PALLOCNOZ (cjMesh, UMPD_MEMORY_TAG);
|
|
|
|
if (psoDest && pVertex && pMesh && pVertexTmp && pMeshTmp && prclExtents && pptlDitherOrg)
|
|
{
|
|
__try
|
|
{
|
|
CaptureRECTL(&prclExtents, &rcl);
|
|
CapturePOINTL(&pptlDitherOrg, &ptl);
|
|
CaptureBits(pVertexTmp, pVertex, sizeof(TRIVERTEX)*nVertex);
|
|
CaptureBits(pMeshTmp, pMesh, cjMesh);
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
WARNING ("NtGdiEngAlphaBlend failed in try/except\n");
|
|
bRet = FALSE;
|
|
}
|
|
|
|
bRet = bRet && bValidVertexMeshData(pVertexTmp,pMeshTmp,nVertex,nMesh,ulMode);
|
|
|
|
if (bRet)
|
|
{
|
|
pco = pUMObjs->GetDDIOBJ(pco, &psoDest->sizlBitmap);
|
|
|
|
bRet = EngGradientFill(psoDest,
|
|
pco,
|
|
pUMObjs->GetDDIOBJ(pxlo),
|
|
pVertexTmp,
|
|
nVertex,
|
|
pMeshTmp,
|
|
nMesh,
|
|
prclExtents,
|
|
pptlDitherOrg,
|
|
ulMode);
|
|
}
|
|
}
|
|
else
|
|
bRet = FALSE;
|
|
|
|
if (pVertexTmp)
|
|
VFREEMEM(pVertexTmp);
|
|
|
|
if (pMeshTmp)
|
|
VFREEMEM(pMeshTmp);
|
|
|
|
FIXUP_THREAD_UMPDOBJS;
|
|
return bRet;
|
|
}
|
|
|
|
|
|
BOOL APIENTRY NtGdiEngTransparentBlt(
|
|
SURFOBJ *psoDst,
|
|
SURFOBJ *psoSrc,
|
|
CLIPOBJ *pco,
|
|
XLATEOBJ *pxlo,
|
|
RECTL *prclDst,
|
|
RECTL *prclSrc,
|
|
ULONG iTransColor,
|
|
ULONG ulReserved
|
|
)
|
|
{
|
|
BOOL bRet = TRUE;
|
|
RECTL rclDst, rclSrc;
|
|
|
|
EXTRACT_THREAD_UMPDOBJS(FALSE);
|
|
|
|
UMPDSURFOBJ umsoDst(psoDst, pUMObjs);
|
|
UMPDSURFOBJ umsoSrc(psoSrc, pUMObjs);
|
|
|
|
psoDst = umsoDst.pso();
|
|
psoSrc = umsoSrc.pso();
|
|
|
|
if (psoDst && psoSrc && prclDst && prclSrc)
|
|
{
|
|
__try
|
|
{
|
|
CaptureRECTL(&prclSrc, &rclSrc);
|
|
CaptureRECTL(&prclDst, &rclDst);
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
WARNING ("NtGdiEngTransparentBlt failed in try/except\n");
|
|
bRet = FALSE;
|
|
}
|
|
|
|
if (bRet && bOrder(prclDst) && bOrder(prclSrc))
|
|
{
|
|
pco = pUMObjs->GetDDIOBJ(pco, &psoDst->sizlBitmap);
|
|
pxlo = pUMObjs->GetDDIOBJ(pxlo);
|
|
|
|
if (bRet = (bCheckSurfaceRect(psoSrc, prclSrc, NULL) && bCheckXlate(psoSrc, pxlo)))
|
|
{
|
|
bRet = EngTransparentBlt(psoDst,
|
|
psoSrc,
|
|
pco,
|
|
pxlo,
|
|
prclDst,
|
|
prclSrc,
|
|
iTransColor,
|
|
ulReserved);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
bRet = FALSE;
|
|
|
|
FIXUP_THREAD_UMPDOBJS;
|
|
return (bRet);
|
|
}
|
|
|
|
|
|
BOOL APIENTRY NtGdiEngTextOut(
|
|
SURFOBJ *pso,
|
|
STROBJ *pstro,
|
|
FONTOBJ *pfo,
|
|
CLIPOBJ *pco,
|
|
RECTL *prclExtra,
|
|
RECTL *prclOpaque,
|
|
BRUSHOBJ *pboFore,
|
|
BRUSHOBJ *pboOpaque,
|
|
POINTL *pptlOrg,
|
|
MIX mix
|
|
)
|
|
{
|
|
BOOL bRet = TRUE;
|
|
RECTL rclExtra, rclOpaque;
|
|
POINTL ptlOrg;
|
|
BRUSHOBJ boTempFore, boTempOpaque;
|
|
|
|
EXTRACT_THREAD_UMPDOBJS(FALSE);
|
|
|
|
UMPDSURFOBJ umso(pso, pUMObjs);
|
|
|
|
pso = umso.pso();
|
|
pstro = pUMObjs->GetDDIOBJ(pstro);
|
|
pfo = pUMObjs->GetDDIOBJ(pfo);
|
|
|
|
MAP_UM_BRUSHOBJ(pUMObjs, pboFore, &boTempFore);
|
|
MAP_UM_BRUSHOBJ(pUMObjs, pboOpaque, &boTempOpaque);
|
|
|
|
if (pso && pstro && pfo && pboFore && pptlOrg)
|
|
{
|
|
__try
|
|
{
|
|
CaptureRECTL(&prclExtra, &rclExtra);
|
|
CaptureRECTL(&prclOpaque, &rclOpaque);
|
|
CapturePOINTL(&pptlOrg, &ptlOrg);
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
WARNING ("NtGdiEngTextOut failed in try/except\n");
|
|
bRet = FALSE;
|
|
}
|
|
|
|
if (bRet)
|
|
{
|
|
pco = pUMObjs->GetDDIOBJ(pco, &pso->sizlBitmap);
|
|
|
|
if (bRet = (!MIXNEEDMASK(mix) || ISPATBRUSH(pboFore)) &&
|
|
bCheckSurfaceRect(pso, prclOpaque, pco))
|
|
{
|
|
|
|
RFONTTMPOBJ rfto(PFO_TO_PRF(pfo));
|
|
|
|
UMPDAcquireRFONTSem(rfto, pUMObjs, 0, 0, NULL);
|
|
|
|
bRet = EngTextOut(pso,
|
|
pstro,
|
|
pfo,
|
|
pco,
|
|
prclExtra,
|
|
prclOpaque,
|
|
pboFore,
|
|
pboOpaque,
|
|
pptlOrg,
|
|
mix);
|
|
|
|
UMPDReleaseRFONTSem(rfto, pUMObjs, NULL, NULL, NULL);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
bRet = FALSE;
|
|
|
|
FIXUP_THREAD_UMPDOBJS;
|
|
return (bRet);
|
|
}
|
|
|
|
HPALETTE APIENTRY NtGdiEngCreatePalette(
|
|
ULONG iMode,
|
|
ULONG cColors,
|
|
ULONG *pulColors,
|
|
FLONG flRed,
|
|
FLONG flGreen,
|
|
FLONG flBlue
|
|
)
|
|
{
|
|
HPALETTE hpal = (HPALETTE)1;
|
|
ULONG pulColorsTmp[256];
|
|
HANDLE hSecure = 0;
|
|
|
|
TRACE_INIT (("Entering NtGdiEngCreatePalette\n"));
|
|
|
|
//
|
|
// cColors has a limit of 64k
|
|
//
|
|
if (cColors > 64 * 1024)
|
|
return 0;
|
|
|
|
if ((iMode == PAL_INDEXED) && cColors)
|
|
{
|
|
if (cColors > 256)
|
|
hpal = (HPALETTE)(ULONG_PTR)bSecureBits(pulColors, cColors*sizeof(ULONG), &hSecure);
|
|
else
|
|
{
|
|
hpal = (HPALETTE)(ULONG_PTR)bSafeReadBits(pulColorsTmp, pulColors, cColors*sizeof(ULONG));
|
|
}
|
|
}
|
|
|
|
if (hpal)
|
|
{
|
|
//
|
|
// set the high bit of iMode to indicate umpd driver
|
|
//
|
|
iMode |= UMPD_FLAG;
|
|
|
|
hpal = EngCreatePalette(iMode, cColors, pulColors, flRed, flGreen, flBlue);
|
|
}
|
|
|
|
if (hSecure)
|
|
{
|
|
MmUnsecureVirtualMemory(hSecure);
|
|
}
|
|
|
|
return hpal;
|
|
}
|
|
|
|
BOOL APIENTRY NtGdiEngDeletePalette(
|
|
IN HPALETTE hpal
|
|
)
|
|
{
|
|
TRACE_INIT (("Entering NtGdiEngDeletePalette\n"));
|
|
|
|
//
|
|
// EngDeletePalette will check if hpal is valid
|
|
// so we don't need to check hpal here
|
|
//
|
|
return (EngDeletePalette(hpal));
|
|
}
|
|
|
|
BOOL APIENTRY NtGdiEngEraseSurface(
|
|
IN SURFOBJ *pso,
|
|
IN RECTL *prcl,
|
|
IN ULONG iColor
|
|
)
|
|
{
|
|
BOOL bRet = TRUE;
|
|
RECTL rcl;
|
|
|
|
EXTRACT_THREAD_UMPDOBJS(FALSE);
|
|
|
|
UMPDSURFOBJ umso(pso, pUMObjs);
|
|
|
|
pso = umso.pso();
|
|
|
|
if (pso)
|
|
{
|
|
__try
|
|
{
|
|
CaptureRECTL(&prcl, &rcl);
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
WARNING ("NtGdiEngEraseSurface failed in try/except\n");
|
|
bRet = FALSE;
|
|
}
|
|
|
|
if (bRet)
|
|
{
|
|
if (bRet = bCheckSurfaceRect(pso, prcl, NULL))
|
|
{
|
|
bRet = EngEraseSurface(pso, prcl, iColor);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
bRet = FALSE;
|
|
|
|
FIXUP_THREAD_UMPDOBJS;
|
|
|
|
return bRet;
|
|
}
|
|
|
|
PATHOBJ* APIENTRY NtGdiCLIPOBJ_ppoGetPath(
|
|
CLIPOBJ *pco
|
|
)
|
|
{
|
|
EXTRACT_THREAD_UMPDOBJS(NULL);
|
|
|
|
PATHOBJ* poRet = pUMObjs->GetCLIPOBJPath(pco);
|
|
|
|
FIXUP_THREAD_UMPDOBJS;
|
|
|
|
return poRet;
|
|
}
|
|
|
|
VOID APIENTRY NtGdiEngDeletePath(
|
|
IN PATHOBJ *ppo
|
|
)
|
|
{
|
|
EXTRACT_THREAD_UMPDOBJS;
|
|
|
|
pUMObjs->DeleteCLIPOBJPath(ppo);
|
|
|
|
FIXUP_THREAD_UMPDOBJS;
|
|
}
|
|
|
|
CLIPOBJ* APIENTRY NtGdiEngCreateClip()
|
|
|
|
{
|
|
EXTRACT_THREAD_UMPDOBJS(NULL);
|
|
|
|
CLIPOBJ* clipRet = pUMObjs->CreateCLIPOBJ();
|
|
|
|
FIXUP_THREAD_UMPDOBJS;
|
|
|
|
return clipRet;
|
|
}
|
|
|
|
VOID APIENTRY NtGdiEngDeleteClip(
|
|
CLIPOBJ *pco
|
|
)
|
|
|
|
{
|
|
EXTRACT_THREAD_UMPDOBJS;
|
|
|
|
pUMObjs->DeleteCLIPOBJ(pco);
|
|
|
|
FIXUP_THREAD_UMPDOBJS;
|
|
}
|
|
|
|
ULONG APIENTRY NtGdiCLIPOBJ_cEnumStart(
|
|
CLIPOBJ *pco,
|
|
BOOL bAll,
|
|
ULONG iType,
|
|
ULONG iDirection,
|
|
ULONG cLimit
|
|
)
|
|
{
|
|
EXTRACT_THREAD_UMPDOBJS(0xffffffff);
|
|
|
|
ULONG ulRet = 0xffffffff;
|
|
|
|
pco = pUMObjs->GetDDIOBJ(pco);
|
|
|
|
if (pco)
|
|
{
|
|
ulRet = CLIPOBJ_cEnumStart(pco,
|
|
bAll,
|
|
iType,
|
|
iDirection,
|
|
cLimit);
|
|
}
|
|
|
|
FIXUP_THREAD_UMPDOBJS;
|
|
|
|
return ulRet;
|
|
}
|
|
|
|
BOOL APIENTRY NtGdiCLIPOBJ_bEnum(
|
|
CLIPOBJ *pco,
|
|
ULONG cj,
|
|
ULONG *pul
|
|
)
|
|
{
|
|
BOOL bRet = DDI_ERROR;
|
|
ULONG *pulTmp;
|
|
|
|
EXTRACT_THREAD_UMPDOBJS(FALSE);
|
|
|
|
pco = pUMObjs->GetDDIOBJ(pco);
|
|
|
|
if (pco)
|
|
{
|
|
pulTmp = (PULONG)PALLOCNOZ(cj, UMPD_MEMORY_TAG);
|
|
|
|
if (pulTmp)
|
|
{
|
|
ULONG cjFilled = 0;
|
|
|
|
bRet = (*(XCLIPOBJ *)pco).bEnum(cj, pulTmp, &cjFilled);
|
|
|
|
if (bRet != DDI_ERROR)
|
|
if (!bSafeCopyBits(pul, pulTmp, cjFilled))
|
|
bRet = DDI_ERROR;
|
|
|
|
VFREEMEM(pulTmp);
|
|
}
|
|
}
|
|
|
|
FIXUP_THREAD_UMPDOBJS;
|
|
return bRet;
|
|
}
|
|
|
|
PVOID APIENTRY NtGdiBRUSHOBJ_pvAllocRbrush(
|
|
BRUSHOBJ *pbo,
|
|
ULONG cj
|
|
)
|
|
{
|
|
EXTRACT_THREAD_UMPDOBJS(NULL);
|
|
|
|
PVOID pvRet = ((pbo = pUMObjs->GetDDIOBJ(pbo)) != NULL) ?
|
|
BRUSHOBJ_pvAllocRbrushUMPD(pbo, cj) :
|
|
NULL;
|
|
|
|
FIXUP_THREAD_UMPDOBJS;
|
|
return pvRet;
|
|
}
|
|
|
|
PVOID APIENTRY NtGdiBRUSHOBJ_pvGetRbrush(
|
|
BRUSHOBJ *pbo
|
|
)
|
|
{
|
|
EXTRACT_THREAD_UMPDOBJS(NULL);
|
|
|
|
PVOID pvRet = ((pbo = pUMObjs->GetDDIOBJ(pbo)) != NULL) ?
|
|
BRUSHOBJ_pvGetRbrushUMPD(pbo) :
|
|
NULL;
|
|
|
|
FIXUP_THREAD_UMPDOBJS;
|
|
return pvRet;
|
|
}
|
|
|
|
|
|
ULONG APIENTRY NtGdiBRUSHOBJ_ulGetBrushColor(
|
|
BRUSHOBJ *pbo
|
|
)
|
|
{
|
|
EXTRACT_THREAD_UMPDOBJS(0);
|
|
|
|
ULONG ulRet = 0;
|
|
BRUSHOBJ *pbokm;
|
|
|
|
if (pbokm = pUMObjs->GetDDIOBJ(pbo))
|
|
{
|
|
if ((pbo->flColorType & BR_ORIGCOLOR) && ((EBRUSHOBJ*)pbokm)->bIsSolid())
|
|
{
|
|
pbokm->flColorType |= BR_ORIGCOLOR;
|
|
}
|
|
ulRet = BRUSHOBJ_ulGetBrushColor(pbokm);
|
|
pbo->flColorType &= ~BR_ORIGCOLOR;
|
|
}
|
|
|
|
FIXUP_THREAD_UMPDOBJS;
|
|
|
|
return ulRet;
|
|
}
|
|
|
|
HANDLE APIENTRY NtGdiBRUSHOBJ_hGetColorTransform(
|
|
BRUSHOBJ *pbo
|
|
)
|
|
{
|
|
EXTRACT_THREAD_UMPDOBJS(NULL);
|
|
|
|
HANDLE hRet = ((pbo = pUMObjs->GetDDIOBJ(pbo)) != NULL) ?
|
|
BRUSHOBJ_hGetColorTransform(pbo) :
|
|
NULL;
|
|
|
|
FIXUP_THREAD_UMPDOBJS;
|
|
|
|
return hRet;
|
|
}
|
|
|
|
BOOL APIENTRY NtGdiXFORMOBJ_bApplyXform(
|
|
XFORMOBJ *pxo,
|
|
ULONG iMode,
|
|
ULONG cPoints,
|
|
PVOID pvIn,
|
|
PVOID pvOut
|
|
)
|
|
|
|
#define APPLYXFORM_STACK_POINTS 4
|
|
|
|
{
|
|
POINTL ptlIn[APPLYXFORM_STACK_POINTS];
|
|
POINTL ptlOut[APPLYXFORM_STACK_POINTS];
|
|
PVOID pvInTmp, pvOutTmp;
|
|
BOOL bRet = FALSE;
|
|
|
|
if (BALLOC_OVERFLOW1(cPoints, POINTL))
|
|
return FALSE;
|
|
|
|
EXTRACT_THREAD_UMPDOBJS(FALSE);
|
|
|
|
pxo = pUMObjs->GetDDIOBJ(pxo);
|
|
|
|
if (pxo && pvIn && pvOut && cPoints)
|
|
{
|
|
if (cPoints <= APPLYXFORM_STACK_POINTS)
|
|
{
|
|
pvInTmp = ptlIn;
|
|
pvOutTmp = ptlOut;
|
|
}
|
|
else
|
|
{
|
|
pvInTmp = PALLOCNOZ(sizeof(POINTL)*cPoints, UMPD_MEMORY_TAG);
|
|
pvOutTmp = PALLOCNOZ(sizeof(POINTL)*cPoints, UMPD_MEMORY_TAG);
|
|
}
|
|
|
|
if (pvInTmp != NULL &&
|
|
pvOutTmp != NULL &&
|
|
bSafeReadBits(pvInTmp, pvIn, cPoints*sizeof(POINTL)))
|
|
{
|
|
bRet = XFORMOBJ_bApplyXform(pxo, iMode, cPoints, pvInTmp, pvOutTmp) &&
|
|
bSafeCopyBits(pvOut, pvOutTmp, cPoints*sizeof(POINTL));
|
|
}
|
|
|
|
if (cPoints > APPLYXFORM_STACK_POINTS)
|
|
{
|
|
if (pvInTmp != NULL)
|
|
VFREEMEM(pvInTmp);
|
|
|
|
if (pvOutTmp != NULL)
|
|
VFREEMEM(pvOutTmp);
|
|
}
|
|
|
|
}
|
|
|
|
FIXUP_THREAD_UMPDOBJS;
|
|
return (bRet);
|
|
}
|
|
|
|
ULONG APIENTRY NtGdiXFORMOBJ_iGetXform(
|
|
XFORMOBJ *pxo,
|
|
XFORML *pxform
|
|
)
|
|
{
|
|
ULONG ulRet = DDI_ERROR;
|
|
XFORML xform;
|
|
|
|
EXTRACT_THREAD_UMPDOBJS(DDI_ERROR);
|
|
|
|
pxo = pUMObjs->GetDDIOBJ(pxo);
|
|
|
|
if (pxo)
|
|
{
|
|
ulRet = XFORMOBJ_iGetXform(pxo, pxform? &xform : NULL);
|
|
|
|
if ((ulRet != DDI_ERROR) && pxform)
|
|
{
|
|
__try
|
|
{
|
|
ProbeAndWriteStructure (pxform, xform, XFORML);
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
ulRet = DDI_ERROR;
|
|
}
|
|
}
|
|
}
|
|
|
|
FIXUP_THREAD_UMPDOBJS;
|
|
return (ulRet);
|
|
}
|
|
|
|
VOID APIENTRY NtGdiFONTOBJ_vGetInfo(
|
|
FONTOBJ *pfo,
|
|
ULONG cjSize,
|
|
FONTINFO *pfi
|
|
)
|
|
{
|
|
FONTINFO *pfiTmp = NULL;
|
|
|
|
EXTRACT_THREAD_UMPDOBJS;
|
|
|
|
pfo = pUMObjs->GetDDIOBJ(pfo);
|
|
|
|
if (pfo)
|
|
{
|
|
if (cjSize && pfi)
|
|
{
|
|
if (pfiTmp = (FONTINFO *)PALLOCNOZ(cjSize, UMPD_MEMORY_TAG))
|
|
{
|
|
FONTOBJ_vGetInfo(pfo, cjSize, pfiTmp);
|
|
|
|
bSafeCopyBits(pfi, pfiTmp, cjSize);
|
|
|
|
VFREEMEM(pfiTmp);
|
|
}
|
|
}
|
|
}
|
|
|
|
FIXUP_THREAD_UMPDOBJS;
|
|
}
|
|
|
|
//
|
|
// FONTOBJ_cGetGlyphs is a service to the font consumer that translates glyph handles into
|
|
// pointers to glyph data. These pointers are valid until the next call to FONTOBJ_cGetGlyphs.
|
|
// this means that we only need to attache one ppvGlyph onto the thread at any time.
|
|
//
|
|
// Note: another way to do this is to pre-allocate a reasonable size of User memory and
|
|
// use that memory for all temporary data buffers, and grow it when we are reaching the limit
|
|
// Thus we save the memory allocation calls.
|
|
//
|
|
ULONG APIENTRY NtGdiFONTOBJ_cGetGlyphs(
|
|
FONTOBJ *pfo,
|
|
ULONG iMode,
|
|
ULONG cGlyph,
|
|
HGLYPH *phg,
|
|
PVOID *ppvGlyph
|
|
)
|
|
{
|
|
GLYPHDATA *pgd, *pgdkm;
|
|
HGLYPH hg;
|
|
ULONG ulRet = 1;
|
|
|
|
EXTRACT_THREAD_UMPDOBJS(0);
|
|
|
|
if ((pfo = pUMObjs->GetDDIOBJ(pfo)) == NULL ||
|
|
(iMode != FO_GLYPHBITS && iMode != FO_PATHOBJ))
|
|
{
|
|
WARNING("Invalid parameter passed to NtGdiFONTOBJ_cGetGlyphs\n");
|
|
FIXUP_THREAD_UMPDOBJS;
|
|
return 0;
|
|
}
|
|
|
|
//
|
|
// Call the engine to retrive glyph data
|
|
//
|
|
// NOTE: DDK documentation is bogus.
|
|
// Font driver only supports cGlyph == 1 case.
|
|
//
|
|
__try
|
|
{
|
|
CaptureDWORD (&phg, &hg);
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
WARNING ("NtGdiFONTOBJ_cGetGlyphs failed in try/except\n");
|
|
ulRet = 0;
|
|
}
|
|
|
|
if (ulRet)
|
|
{
|
|
RFONTTMPOBJ rfto(PFO_TO_PRF(pfo));
|
|
|
|
UMPDAcquireRFONTSem(rfto, pUMObjs, 0, 0, NULL);
|
|
|
|
if ((ulRet = FONTOBJ_cGetGlyphs(pfo, iMode, 1, phg, (PVOID *) &pgd)) == 1)
|
|
{
|
|
//
|
|
// Thunk GLYPHDATA structure
|
|
//
|
|
|
|
pgdkm = pgd;
|
|
|
|
if (!pUMObjs->ThunkMemBlock((PVOID *) &pgd, sizeof(GLYPHDATA)))
|
|
{
|
|
WARNING("Couldn't thunk GLYPHDATA structure\n");
|
|
ulRet = 0;
|
|
}
|
|
else if (iMode == FO_GLYPHBITS)
|
|
{
|
|
//
|
|
// Thunk GLYPHBITS structure
|
|
//
|
|
|
|
if (pgdkm->gdf.pgb != NULL &&
|
|
(pgd->gdf.pgb = pUMObjs->CacheGlyphBits(pgdkm->gdf.pgb)) == NULL)
|
|
{
|
|
WARNING("Couldn't thunk GLYPHBITS structure\n");
|
|
ulRet = 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Thunk PATHOBJ
|
|
//
|
|
|
|
if (pgdkm->gdf.ppo != NULL &&
|
|
(pgd->gdf.ppo = pUMObjs->CacheGlyphPath(pgdkm->gdf.ppo)) == NULL)
|
|
{
|
|
WARNING("Couldn't thunk PATHOBJ structure\n");
|
|
ulRet = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
UMPDReleaseRFONTSem(rfto, pUMObjs, NULL, NULL, NULL);
|
|
|
|
if (ulRet != 0)
|
|
{
|
|
__try
|
|
{
|
|
ProbeAndWriteStructure (ppvGlyph, (PVOID)pgd, PVOID);
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
WARNING ("fail to write in ppvGlyph\n");
|
|
ulRet = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
FIXUP_THREAD_UMPDOBJS;
|
|
return ulRet;
|
|
}
|
|
|
|
|
|
ULONG APIENTRY NtGdiFONTOBJ_cGetAllGlyphHandles(
|
|
IN FONTOBJ *pfo,
|
|
OUT HGLYPH *phg
|
|
)
|
|
{
|
|
ULONG ulCount = 0;
|
|
HGLYPH *phgTmp = NULL;
|
|
ULONG ulRet = 0;
|
|
|
|
EXTRACT_THREAD_UMPDOBJS(0);
|
|
|
|
pfo = pUMObjs->GetDDIOBJ(pfo);
|
|
|
|
if (pfo)
|
|
{
|
|
if (phg)
|
|
{
|
|
if (ulCount = FONTOBJ_cGetAllGlyphHandles(pfo, NULL))
|
|
{
|
|
// we are a little bit over cautious here,well...
|
|
if (BALLOC_OVERFLOW1(ulCount, HGLYPH))
|
|
{
|
|
FIXUP_THREAD_UMPDOBJS;
|
|
return NULL;
|
|
}
|
|
|
|
phgTmp = (HGLYPH *)PALLOCNOZ(ulCount*sizeof(HGLYPH), UMPD_MEMORY_TAG);
|
|
}
|
|
}
|
|
|
|
ulRet = FONTOBJ_cGetAllGlyphHandles(pfo, phgTmp);
|
|
ASSERTGDI(phg == NULL || ulRet == ulCount, "NtGdiFONTOBJ_cGetAllGlyphHandles: inconsistent return values from FONTOBJ_cGetAllGlyphHandles\n");
|
|
|
|
if (ulRet && phg && phgTmp)
|
|
{
|
|
if (!bSafeCopyBits(phg, phgTmp, ulCount * sizeof(HGLYPH)))
|
|
ulRet = NULL;
|
|
}
|
|
|
|
if (phgTmp)
|
|
{
|
|
VFREEMEM(phgTmp);
|
|
}
|
|
}
|
|
|
|
FIXUP_THREAD_UMPDOBJS;
|
|
return ulRet;
|
|
}
|
|
|
|
XFORMOBJ* APIENTRY NtGdiFONTOBJ_pxoGetXform(
|
|
FONTOBJ *pfo
|
|
)
|
|
{
|
|
EXTRACT_THREAD_UMPDOBJS(NULL);
|
|
|
|
XFORMOBJ* xoRet= pUMObjs->GetFONTOBJXform(pfo);
|
|
|
|
FIXUP_THREAD_UMPDOBJS;
|
|
return xoRet;
|
|
}
|
|
|
|
|
|
//
|
|
// If the return value is a system address, we copy it into user memory
|
|
//
|
|
// IMPORTANT!!
|
|
// We assume FD_GLYPHSET information is stored in one contiguous block
|
|
// of memory and FD_GLYPHSET.cjThis field is the size of the entire block.
|
|
// HGLYPH arrays in each WCRUN are part of the block, placed just after
|
|
// FD_GLYPHSET structure itself.
|
|
//
|
|
BOOL
|
|
GreCopyFD_GLYPHSET(
|
|
FD_GLYPHSET *dst,
|
|
FD_GLYPHSET *src,
|
|
ULONG cjSize,
|
|
BOOL bFromKernel
|
|
)
|
|
|
|
{
|
|
ULONG size;
|
|
PBYTE phg, pbMax;
|
|
|
|
//
|
|
// bFromKernel TRUE: we are copying from kernel mode address(src) to user mode address (dst)
|
|
// the src should contain everything in one chunk of memory
|
|
//
|
|
// FALSE: copying from user mode (src) to kernel mode (dst)
|
|
// glyph indices in src might be stored in a different chunk of memory from src
|
|
//
|
|
|
|
size = bFromKernel ? cjSize : offsetof(FD_GLYPHSET, awcrun) + src->cRuns * sizeof(WCRUN);
|
|
RtlCopyMemory(dst, src, size);
|
|
|
|
dst->cjThis = cjSize;
|
|
pbMax = (PBYTE)dst + cjSize;
|
|
phg = (PBYTE)dst + size;
|
|
|
|
//
|
|
// Patch up memory pointers in each WCRUN structure
|
|
//
|
|
|
|
ULONG index, offset;
|
|
|
|
for (index=0; index < src->cRuns; index++)
|
|
{
|
|
if (src->awcrun[index].phg != NULL)
|
|
{
|
|
if (bFromKernel)
|
|
{
|
|
offset = (ULONG)((PBYTE) src->awcrun[index].phg - (PBYTE) src);
|
|
|
|
if (offset >= cjSize)
|
|
{
|
|
WARNING("GreCopyFD_GLYPHSET failed.\n");
|
|
return FALSE;
|
|
}
|
|
dst->awcrun[index].phg = (HGLYPH*) ((PBYTE) dst + offset);
|
|
}
|
|
else
|
|
{
|
|
size = src->awcrun[index].cGlyphs * sizeof(HGLYPH);
|
|
|
|
if (phg + size <= pbMax)
|
|
{
|
|
RtlCopyMemory(phg, src->awcrun[index].phg, size);
|
|
dst->awcrun[index].phg = (HGLYPH*) phg;
|
|
phg += size;
|
|
}
|
|
else
|
|
return FALSE;
|
|
}
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
FD_GLYPHSET * APIENTRY NtGdiFONTOBJ_pfdg(
|
|
FONTOBJ *pfo
|
|
)
|
|
{
|
|
FD_GLYPHSET *pfdg = NULL, *pfdgTmp;
|
|
ULONG cjSize;
|
|
|
|
EXTRACT_THREAD_UMPDOBJS(NULL);
|
|
|
|
//
|
|
// Check if this function has already been
|
|
// called during the current DDI entrypoint
|
|
//
|
|
|
|
if (! (pfo = pUMObjs->GetDDIOBJ(pfo)) ||
|
|
(pfdg = pUMObjs->pfdg()) != NULL)
|
|
{
|
|
FIXUP_THREAD_UMPDOBJS;
|
|
return pfdg;
|
|
}
|
|
|
|
//
|
|
// Call FONTOBJ_pifi and cache the pointer in UMPDOBJ
|
|
//
|
|
|
|
RFONTTMPOBJ rfto(PFO_TO_PRF(pfo));
|
|
|
|
UMPDAcquireRFONTSem(rfto, pUMObjs, 0, 0, NULL);
|
|
|
|
pfdgTmp = NULL;
|
|
|
|
if ((pfdg = FONTOBJ_pfdg(pfo)) != NULL)
|
|
{
|
|
if (IS_SYSTEM_ADDRESS(pfdg))
|
|
{
|
|
if ((cjSize = SZ_GLYPHSET(pfdg->cRuns, pfdg->cGlyphsSupported)) &&
|
|
(pfdgTmp = (FD_GLYPHSET *) pUMObjs->AllocUserMem(cjSize)))
|
|
{
|
|
if (GreCopyFD_GLYPHSET(pfdgTmp, pfdg, cjSize, TRUE))
|
|
pUMObjs->pfdg(pfdgTmp);
|
|
else
|
|
pfdgTmp = NULL;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pfdgTmp = pfdg;
|
|
pUMObjs->pfdg(pfdgTmp);
|
|
}
|
|
}
|
|
|
|
UMPDReleaseRFONTSem(rfto, pUMObjs, NULL, NULL, NULL);
|
|
|
|
FIXUP_THREAD_UMPDOBJS;
|
|
return pfdgTmp;
|
|
}
|
|
|
|
PFD_GLYPHATTR APIENTRY NtGdiFONTOBJ_pQueryGlyphAttrs(
|
|
FONTOBJ *pfo,
|
|
ULONG iMode
|
|
)
|
|
{
|
|
PFD_GLYPHATTR pfdga, pfdgaTmp;
|
|
ULONG i;
|
|
|
|
EXTRACT_THREAD_UMPDOBJS(FALSE);
|
|
|
|
if ((pfo = pUMObjs->GetDDIOBJ(pfo)) == NULL)
|
|
{
|
|
WARNING("Invalid parameter passed to NtGdiFONTOBJ_pQueryGlyphAttrs\n");
|
|
FIXUP_THREAD_UMPDOBJS;
|
|
return FALSE;
|
|
}
|
|
|
|
pfdga = NULL;
|
|
|
|
if ((pfdgaTmp = pUMObjs->pfdga()) == NULL)
|
|
{
|
|
|
|
RFONTTMPOBJ rfto(PFO_TO_PRF(pfo));
|
|
|
|
UMPDAcquireRFONTSem(rfto, pUMObjs, 0, 0, NULL);
|
|
|
|
pfdgaTmp = FONTOBJ_pQueryGlyphAttrs(pfo, iMode);
|
|
|
|
if (pfdgaTmp)
|
|
{
|
|
ULONG cjSize;
|
|
|
|
cjSize = ((PFD_GLYPHATTR)pfdgaTmp)->cjThis;
|
|
pfdga = (PFD_GLYPHATTR) pUMObjs->AllocUserMem(cjSize);
|
|
|
|
if (pfdga)
|
|
{
|
|
RtlCopyMemory((PVOID) pfdga, (PVOID) pfdgaTmp, cjSize);
|
|
pUMObjs->pfdga(pfdga);
|
|
}
|
|
}
|
|
|
|
UMPDReleaseRFONTSem(rfto, pUMObjs, NULL, NULL, NULL);
|
|
|
|
}
|
|
else
|
|
pfdga = pfdgaTmp;
|
|
|
|
FIXUP_THREAD_UMPDOBJS;
|
|
return pfdga;
|
|
}
|
|
|
|
//
|
|
// if the return value is a system address, we copy it into user memory
|
|
//
|
|
IFIMETRICS * APIENTRY NtGdiFONTOBJ_pifi(
|
|
FONTOBJ *pfo
|
|
)
|
|
{
|
|
IFIMETRICS *pifi = NULL, *pifiTmp;
|
|
|
|
EXTRACT_THREAD_UMPDOBJS(NULL);
|
|
|
|
//
|
|
// Check if this function has already been
|
|
// called during the current DDI entrypoint
|
|
//
|
|
|
|
if (! (pfo = pUMObjs->GetDDIOBJ(pfo)) ||
|
|
(pifi = pUMObjs->pifi()) != NULL)
|
|
{
|
|
FIXUP_THREAD_UMPDOBJS;
|
|
return pifi;
|
|
}
|
|
|
|
//
|
|
// Call FONTOBJ_pifi and cache the pointer in UMPDOBJ
|
|
//
|
|
|
|
RFONTTMPOBJ rfto(PFO_TO_PRF(pfo));
|
|
|
|
UMPDAcquireRFONTSem(rfto, pUMObjs, 0, 0, NULL);
|
|
|
|
if ((pifi = FONTOBJ_pifi(pfo)) != NULL &&
|
|
IS_SYSTEM_ADDRESS(pifi))
|
|
{
|
|
pifiTmp = pifi;
|
|
pifi = (PIFIMETRICS) pUMObjs->AllocUserMem(pifi->cjThis);
|
|
|
|
if (pifi != NULL)
|
|
{
|
|
RtlCopyMemory (pifi, pifiTmp, pifiTmp->cjThis);
|
|
pUMObjs->pifi(pifi);
|
|
}
|
|
}
|
|
|
|
UMPDReleaseRFONTSem(rfto, pUMObjs, NULL, NULL, NULL);
|
|
|
|
FIXUP_THREAD_UMPDOBJS;
|
|
return pifi;
|
|
}
|
|
|
|
|
|
BOOL APIENTRY NtGdiSTROBJ_bEnumInternal(
|
|
STROBJ *pstro,
|
|
ULONG *pc,
|
|
PGLYPHPOS *ppgpos,
|
|
BOOL bPositionsOnly
|
|
)
|
|
{
|
|
GLYPHPOS *pgp, *pgpTmp;
|
|
ULONG c;
|
|
BOOL bRet;
|
|
|
|
EXTRACT_THREAD_UMPDOBJS(DDI_ERROR);
|
|
|
|
//
|
|
// bRet from STROBJ_bEnum could have 3 different values:
|
|
// TRUE: more glyphs remained to be enumurated
|
|
// FALSE: no more glyphs to be enumrated
|
|
// DDI_ERROR: failure
|
|
//
|
|
|
|
if ((pstro = pUMObjs->GetDDIOBJ(pstro)) == NULL ||
|
|
((bRet = bPositionsOnly ? STROBJ_bEnumPositionsOnly(pstro, &c, &pgp) : STROBJ_bEnum(pstro, &c, &pgp)) == DDI_ERROR))
|
|
{
|
|
FIXUP_THREAD_UMPDOBJS;
|
|
return DDI_ERROR;
|
|
}
|
|
else
|
|
{
|
|
// over cautious here
|
|
if (BALLOC_OVERFLOW1(c, GLYPHPOS) ||
|
|
(!(pgpTmp = (GLYPHPOS *) pUMObjs->AllocUserMem(sizeof(GLYPHPOS) * c))))
|
|
{
|
|
FIXUP_THREAD_UMPDOBJS;
|
|
return DDI_ERROR;
|
|
}
|
|
}
|
|
|
|
RtlCopyMemory(pgpTmp, pgp, sizeof(GLYPHPOS)*c);
|
|
|
|
__try
|
|
{
|
|
ProbeAndWriteStructure(ppgpos, pgpTmp, PVOID);
|
|
ProbeAndWriteUlong(pc, c);
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
WARNING("fail to write in ppgpos or pc\n");
|
|
c = 0;
|
|
bRet = FALSE;
|
|
}
|
|
|
|
//
|
|
// NULL out GLYPHPOS.pgdf field to force the driver
|
|
// to call FONTOBJ_cGetGlyphs.
|
|
//
|
|
|
|
for (ULONG i=0; i < c; i++)
|
|
pgpTmp[i].pgdf = NULL;
|
|
|
|
FIXUP_THREAD_UMPDOBJS;
|
|
return bRet;
|
|
}
|
|
|
|
BOOL APIENTRY NtGdiSTROBJ_bEnum(
|
|
STROBJ *pstro,
|
|
ULONG *pc,
|
|
PGLYPHPOS *ppgpos
|
|
)
|
|
{
|
|
return NtGdiSTROBJ_bEnumInternal(pstro, pc, ppgpos, FALSE);
|
|
}
|
|
|
|
BOOL APIENTRY NtGdiSTROBJ_bEnumPositionsOnly(
|
|
STROBJ *pstro,
|
|
ULONG *pc,
|
|
PGLYPHPOS *ppgpos
|
|
)
|
|
{
|
|
return NtGdiSTROBJ_bEnumInternal(pstro, pc, ppgpos, TRUE);
|
|
}
|
|
|
|
|
|
BOOL APIENTRY NtGdiSTROBJ_bGetAdvanceWidths(
|
|
STROBJ *pstro,
|
|
ULONG iFirst,
|
|
ULONG c,
|
|
POINTQF *pptqD
|
|
)
|
|
{
|
|
|
|
BOOL bRet = FALSE;
|
|
POINTQF *pptqDTmp;
|
|
|
|
EXTRACT_THREAD_UMPDOBJS(FALSE);
|
|
|
|
if ((pstro = pUMObjs->GetDDIOBJ(pstro)) == NULL ||
|
|
BALLOC_OVERFLOW1(c, POINTQF) ||
|
|
!(pptqDTmp = (POINTQF *) pUMObjs->AllocUserMem(sizeof(POINTQF) * c)))
|
|
{
|
|
FIXUP_THREAD_UMPDOBJS;
|
|
return bRet;
|
|
}
|
|
|
|
// kernel mode can not fail
|
|
|
|
bRet = STROBJ_bGetAdvanceWidths(pstro, iFirst, c, pptqDTmp);
|
|
|
|
if (bRet)
|
|
{
|
|
__try
|
|
{
|
|
ProbeAndWriteAlignedBuffer( pptqD, pptqDTmp, sizeof(POINTQF) * c, sizeof(LARGE_INTEGER));
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
WARNING("fail to write in ppgpos or pc\n");
|
|
bRet = FALSE;
|
|
}
|
|
}
|
|
|
|
FIXUP_THREAD_UMPDOBJS;
|
|
return bRet;
|
|
}
|
|
|
|
|
|
|
|
VOID APIENTRY NtGdiSTROBJ_vEnumStart(
|
|
IN STROBJ *pstro
|
|
)
|
|
{
|
|
EXTRACT_THREAD_UMPDOBJS;
|
|
|
|
if ((pstro = pUMObjs->GetDDIOBJ(pstro)) != NULL)
|
|
STROBJ_vEnumStart(pstro);
|
|
|
|
FIXUP_THREAD_UMPDOBJS;
|
|
}
|
|
|
|
DWORD APIENTRY NtGdiSTROBJ_dwGetCodePage(
|
|
STROBJ *pstro
|
|
)
|
|
|
|
{
|
|
EXTRACT_THREAD_UMPDOBJS(0);
|
|
|
|
DWORD dwRet = ((pstro = pUMObjs->GetDDIOBJ(pstro)) != NULL) ?
|
|
STROBJ_dwGetCodePage(pstro) :
|
|
0;
|
|
|
|
FIXUP_THREAD_UMPDOBJS;
|
|
return dwRet;
|
|
}
|
|
|
|
//
|
|
// private
|
|
//
|
|
DHPDEV NtGdiGetDhpdev(HDEV hdev)
|
|
{
|
|
return ValidUmpdHdev(hdev) ? ((PPDEV)hdev)->dhpdev : NULL;
|
|
}
|
|
|
|
BOOL NtGdiSetPUMPDOBJ(
|
|
HUMPD humpd,
|
|
BOOL bStoreID,
|
|
HUMPD *phumpd,
|
|
BOOL *pbWOW64
|
|
)
|
|
{
|
|
UMPDREF umpdRef(humpd);
|
|
|
|
if (
|
|
(bStoreID && humpd == NULL) ||
|
|
(bStoreID && umpdRef.pumpdGet() == NULL) ||
|
|
(!bStoreID && phumpd == NULL)
|
|
)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
PW32THREAD pw32thread = W32GetCurrentThread();
|
|
HUMPD hSaved = pw32thread->pUMPDObj ? (HUMPD)((PUMPDOBJ)pw32thread->pUMPDObj)->hGet() : 0;
|
|
HUMPD humpdTmp;
|
|
|
|
if (!bStoreID)
|
|
{
|
|
__try
|
|
{
|
|
ProbeAndReadBuffer(&humpdTmp,phumpd,sizeof(HUMPD));
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
WARNING("NtGdiSetPUMPDOBJ probe phumpd failed\n");
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
if (bStoreID)
|
|
{
|
|
BOOL bWOW64;
|
|
|
|
bWOW64 = umpdRef.bWOW64();
|
|
|
|
__try
|
|
{
|
|
if (pbWOW64)
|
|
{
|
|
ProbeAndWriteBuffer(pbWOW64, &bWOW64, sizeof(BOOL));
|
|
}
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
WARNING("NtGdiSetPUMPDOBJ: bad pumpdobj or probe pbWOW64 failed\n");
|
|
return FALSE;
|
|
}
|
|
#if defined(_WIN64)
|
|
if (bWOW64)
|
|
{
|
|
ASSERTGDI(pw32thread->pClientID == NULL, "NtGdiSetPUMPDOBJ: existing non-null pClientID\n");
|
|
|
|
if (pw32thread->pClientID == NULL)
|
|
{
|
|
KERNEL_PVOID pclientID = (KERNEL_PVOID)PALLOCMEM(sizeof(PRINTCLIENTID), 'dipG');
|
|
|
|
if (pclientID)
|
|
{
|
|
__try
|
|
{
|
|
((PRINTCLIENTID*)pclientID)->clientTid = umpdRef.clientTid();
|
|
((PRINTCLIENTID*)pclientID)->clientPid = umpdRef.clientPid();
|
|
pw32thread->pClientID = pclientID;
|
|
|
|
ProbeAndWriteBuffer(phumpd, &hSaved, sizeof(HUMPD));
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
WARNING("NtGdiSetPUMPDOBJ: wow64 failed to access pumpdobj or ppumpdobj\n");
|
|
pw32thread->pClientID = NULL;
|
|
VFREEMEM(pclientID);
|
|
return FALSE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
WARNING("NtGdiSetPUMPDOBJ: failed to allocate pclientID\n");
|
|
return FALSE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
WARNING("NtGdiSetPUMPDOBJ: bWOW64 and existing pClientID\n");
|
|
return FALSE;
|
|
}
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
__try
|
|
{
|
|
ProbeAndWriteBuffer(phumpd, &hSaved, sizeof(HUMPD));
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
WARNING("NtGdiSetPUMPDOBJ: failed to access ppumpdobj\n");
|
|
return FALSE;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (humpdTmp != hSaved)
|
|
{
|
|
WARNING("NtGdiSetPUMPDOBJ: mismatched pumpdobj\n");
|
|
return FALSE;
|
|
}
|
|
#if defined(_WIN64)
|
|
UMPDREF umpdSaved(hSaved);
|
|
|
|
ASSERTGDI(umpdSaved.pumpdGet(), "NtGdiSetPUMPDOBJ: saved pumpdobj is NULL\n");
|
|
|
|
if (umpdSaved.bWOW64() && pw32thread->pClientID)
|
|
{
|
|
VFREEMEM(pw32thread->pClientID);
|
|
pw32thread->pClientID = NULL;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
pw32thread->pUMPDObj = umpdRef.pumpdGet();
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
//
|
|
// private, called only for WOW64 printing
|
|
//
|
|
|
|
BOOL NtGdiBRUSHOBJ_DeleteRbrush(BRUSHOBJ *pbo, BRUSHOBJ *pboB)
|
|
{
|
|
EXTRACT_THREAD_UMPDOBJS(FALSE);
|
|
|
|
BRUSHOBJ *pbokm;
|
|
|
|
if (pbo)
|
|
{
|
|
pbokm = pUMObjs->GetDDIOBJ(pbo);
|
|
|
|
if (pbokm && pbokm->pvRbrush && !IS_SYSTEM_ADDRESS(pbokm->pvRbrush))
|
|
{
|
|
EngFreeUserMem(DBRUSHSTART(pbokm->pvRbrush));
|
|
pbokm->pvRbrush = NULL;
|
|
}
|
|
}
|
|
|
|
if (pboB)
|
|
{
|
|
pbokm = pUMObjs->GetDDIOBJ(pboB);
|
|
|
|
if (pbokm && pbokm->pvRbrush && !IS_SYSTEM_ADDRESS(pbokm->pvRbrush))
|
|
{
|
|
EngFreeUserMem(DBRUSHSTART(pbokm->pvRbrush));
|
|
pbokm->pvRbrush = NULL;
|
|
}
|
|
}
|
|
|
|
FIXUP_THREAD_UMPDOBJS;
|
|
return TRUE;
|
|
}
|
|
|
|
// Private, used only for WOW64 printing
|
|
|
|
BOOL APIENTRY NtGdiUMPDEngFreeUserMem(KERNEL_PVOID *ppv)
|
|
{
|
|
#if defined(_WIN64)
|
|
PVOID pv = NULL, pvTmp;
|
|
|
|
__try
|
|
{
|
|
if (ppv)
|
|
{
|
|
ProbeAndReadBuffer(&pv, ppv, sizeof(PVOID));
|
|
ProbeForRead(pv, sizeof(ULONG), sizeof(ULONG));
|
|
|
|
// Winbug 397346
|
|
// We are doing the following probing since EngFreeUserMem
|
|
// does NOT try-except/probe while accessing pvTmp.
|
|
|
|
pvTmp = (PBYTE)pv - sizeof(ULONG_PTR)*4;
|
|
ProbeForRead(pvTmp, sizeof(ULONG_PTR)*4, sizeof(ULONG_PTR));
|
|
}
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
WARNING("NtGdiUMPDEngFreeUserMem: bad input pointer\n");
|
|
return FALSE;
|
|
}
|
|
|
|
if (pv)
|
|
EngFreeUserMem(pv);
|
|
#endif
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
HSURF APIENTRY NtGdiEngCreateDeviceSurface(
|
|
DHSURF dhsurf,
|
|
SIZEL sizl,
|
|
ULONG iFormatCompat
|
|
)
|
|
{
|
|
TRACE_INIT (("Entering NtGdiEngCreateDeviceSurface\n"));
|
|
|
|
if ((iFormatCompat > BMF_8RLE) || (iFormatCompat < BMF_1BPP))
|
|
return 0;
|
|
|
|
//
|
|
// set high bit of iFormatCompat to indicate umpd driver
|
|
//
|
|
return (EngCreateDeviceSurface(dhsurf, sizl, iFormatCompat|= UMPD_FLAG));
|
|
}
|
|
|
|
HBITMAP APIENTRY NtGdiEngCreateDeviceBitmap(
|
|
DHSURF dhsurf,
|
|
SIZEL sizl,
|
|
ULONG iFormatCompat
|
|
)
|
|
{
|
|
if (!ValidUmpdSizl(sizl))
|
|
return 0;
|
|
|
|
if ((iFormatCompat > BMF_8RLE) || (iFormatCompat < BMF_1BPP))
|
|
return 0;
|
|
|
|
return EngCreateDeviceBitmap(dhsurf, sizl, iFormatCompat | UMPD_FLAG);
|
|
}
|
|
|
|
VOID APIENTRY NtGdiPATHOBJ_vGetBounds(
|
|
IN PATHOBJ *ppo,
|
|
OUT PRECTFX prectfx
|
|
)
|
|
{
|
|
RECTFX rectfx;
|
|
EXTRACT_THREAD_UMPDOBJS;
|
|
|
|
ppo = pUMObjs->GetDDIOBJ(ppo);
|
|
|
|
if (ppo)
|
|
{
|
|
PATHOBJ_vGetBounds(ppo, &rectfx);
|
|
|
|
__try
|
|
{
|
|
ProbeAndWriteStructure(prectfx, rectfx, RECTFX);
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
WARNING("fail to write into prectfx\n");
|
|
}
|
|
}
|
|
|
|
FIXUP_THREAD_UMPDOBJS;
|
|
}
|
|
|
|
BOOL APIENTRY NtGdiPATHOBJ_bEnum(
|
|
IN PATHOBJ *ppo,
|
|
OUT PATHDATA *ppd
|
|
)
|
|
{
|
|
PATHDATA pathdata;
|
|
BOOL bRet = FALSE;
|
|
PVOID pvTmp = NULL;
|
|
|
|
EXTRACT_THREAD_UMPDOBJS(FALSE);
|
|
|
|
if (ppo = pUMObjs->GetDDIOBJ(ppo))
|
|
{
|
|
bRet = PATHOBJ_bEnum(ppo, &pathdata);
|
|
|
|
// over cautious
|
|
if (BALLOC_OVERFLOW1(pathdata.count, POINTFIX))
|
|
{
|
|
FIXUP_THREAD_UMPDOBJS;
|
|
return FALSE;
|
|
}
|
|
|
|
if (pvTmp = pUMObjs->AllocUserMem(sizeof(POINTFX) * pathdata.count))
|
|
{
|
|
RtlCopyMemory(pvTmp, pathdata.pptfx, sizeof(POINTFX) * pathdata.count);
|
|
pathdata.pptfx = (POINTFIX *) pvTmp;
|
|
}
|
|
else
|
|
bRet = FALSE;
|
|
}
|
|
|
|
if (pvTmp == NULL)
|
|
RtlZeroMemory(&pathdata, sizeof(pathdata));
|
|
|
|
__try
|
|
{
|
|
ProbeAndWriteStructure(ppd, pathdata, PATHDATA);
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
WARNING("fail to write into ppd\n");
|
|
bRet = FALSE;
|
|
}
|
|
|
|
FIXUP_THREAD_UMPDOBJS;
|
|
return bRet;
|
|
}
|
|
|
|
|
|
VOID APIENTRY NtGdiPATHOBJ_vEnumStart(
|
|
IN PATHOBJ *ppo
|
|
)
|
|
{
|
|
EXTRACT_THREAD_UMPDOBJS;
|
|
|
|
if ((ppo = pUMObjs->GetDDIOBJ(ppo)) != NULL)
|
|
PATHOBJ_vEnumStart(ppo);
|
|
|
|
FIXUP_THREAD_UMPDOBJS;
|
|
}
|
|
|
|
VOID APIENTRY NtGdiPATHOBJ_vEnumStartClipLines(
|
|
PATHOBJ *ppo,
|
|
CLIPOBJ *pco,
|
|
SURFOBJ *pso,
|
|
LINEATTRS *pla
|
|
)
|
|
|
|
{
|
|
LINEATTRS lineattrs;
|
|
|
|
EXTRACT_THREAD_UMPDOBJS;
|
|
|
|
UMPDSURFOBJ umso(pso, pUMObjs);
|
|
|
|
pso = umso.pso();
|
|
ppo = pUMObjs->GetDDIOBJ(ppo);
|
|
|
|
if (pso && ppo && bCaptureLINEATTRS(&pla, &lineattrs))
|
|
{
|
|
pco = pUMObjs->GetDDIOBJ(pco, &pso->sizlBitmap);
|
|
PATHOBJ_vEnumStartClipLines(ppo, pco, pso, pla);
|
|
|
|
if (pla && pla->pstyle)
|
|
VFREEMEM(pla->pstyle);
|
|
}
|
|
|
|
FIXUP_THREAD_UMPDOBJS;
|
|
}
|
|
|
|
|
|
BOOL APIENTRY NtGdiPATHOBJ_bEnumClipLines(
|
|
PATHOBJ *ppo,
|
|
ULONG cb,
|
|
CLIPLINE *pcl
|
|
)
|
|
|
|
{
|
|
BOOL bRet = FALSE;
|
|
PVOID pvTmp = NULL;
|
|
|
|
EXTRACT_THREAD_UMPDOBJS(FALSE);
|
|
|
|
if (cb <= sizeof(CLIPLINE))
|
|
{
|
|
FIXUP_THREAD_UMPDOBJS;
|
|
return(FALSE);
|
|
}
|
|
|
|
if ((ppo = pUMObjs->GetDDIOBJ(ppo)) != NULL &&
|
|
(pvTmp = PALLOCNOZ(cb, UMPD_MEMORY_TAG)) != NULL)
|
|
{
|
|
bRet = PATHOBJ_bEnumClipLines(ppo, cb, (CLIPLINE *) pvTmp);
|
|
}
|
|
|
|
__try
|
|
{
|
|
ProbeForWrite(pcl, cb, sizeof(ULONG));
|
|
|
|
if (pvTmp != NULL)
|
|
RtlCopyMemory(pcl, pvTmp, cb);
|
|
else
|
|
RtlZeroMemory(pcl, cb);
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
bRet = FALSE;
|
|
}
|
|
|
|
if (pvTmp != NULL)
|
|
VFREEMEM(pvTmp);
|
|
|
|
FIXUP_THREAD_UMPDOBJS;
|
|
return bRet;
|
|
}
|
|
|
|
|
|
PVOID APIENTRY NtGdiFONTOBJ_pvTrueTypeFontFile(
|
|
IN FONTOBJ *pfo,
|
|
OUT ULONG *pcjFile
|
|
)
|
|
{
|
|
EXTRACT_THREAD_UMPDOBJS(NULL);
|
|
|
|
PVOID pBase, p = NULL;
|
|
ULONG size;
|
|
|
|
if ((pfo = pUMObjs->GetDDIOBJ(pfo)) != NULL &&
|
|
(p = pUMObjs->pvFontFile(&size)) == NULL &&
|
|
(p = FONTOBJ_pvTrueTypeFontFileUMPD(pfo, &size, &pBase)) != NULL)
|
|
{
|
|
pUMObjs->pvFontFile(p, pBase, size);
|
|
}
|
|
|
|
if (p == NULL)
|
|
size = 0;
|
|
|
|
if (pcjFile != NULL)
|
|
{
|
|
__try
|
|
{
|
|
ProbeAndWriteStructure(pcjFile, size, DWORD);
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
WARNING("fail to write into pcjFilie\n");
|
|
p = NULL;
|
|
}
|
|
}
|
|
|
|
FIXUP_THREAD_UMPDOBJS;
|
|
return p;
|
|
}
|
|
|
|
HANDLE APIENTRY NtGdiXLATEOBJ_hGetColorTransform(
|
|
XLATEOBJ *pxlo
|
|
)
|
|
{
|
|
EXTRACT_THREAD_UMPDOBJS(NULL);
|
|
|
|
HANDLE hRet = ((pxlo = pUMObjs->GetDDIOBJ(pxlo)) != NULL) ?
|
|
XLATEOBJ_hGetColorTransform(pxlo) :
|
|
NULL;
|
|
|
|
FIXUP_THREAD_UMPDOBJS;
|
|
return hRet;
|
|
}
|
|
|
|
ULONG APIENTRY NtGdiXLATEOBJ_cGetPalette(
|
|
IN XLATEOBJ* pxlo,
|
|
IN ULONG iPal,
|
|
IN ULONG cPal,
|
|
IN ULONG *pPal
|
|
)
|
|
{
|
|
ULONG ulRet = 0;
|
|
ULONG *pPalTmp = NULL;
|
|
|
|
EXTRACT_THREAD_UMPDOBJS(0);
|
|
|
|
pxlo = pUMObjs->GetDDIOBJ(pxlo);
|
|
|
|
if (pxlo)
|
|
{
|
|
if (pPal)
|
|
{
|
|
if (BALLOC_OVERFLOW1(cPal, DWORD))
|
|
{
|
|
FIXUP_THREAD_UMPDOBJS;
|
|
return 0;
|
|
}
|
|
|
|
pPalTmp = (PULONG)PALLOCNOZ(sizeof(DWORD)*cPal, UMPD_MEMORY_TAG);
|
|
}
|
|
|
|
if (pPalTmp)
|
|
{
|
|
ulRet = XLATEOBJ_cGetPalette(pxlo, iPal, cPal, pPalTmp);
|
|
|
|
if (ulRet)
|
|
{
|
|
if (!bSafeCopyBits(pPal, pPalTmp, sizeof(DWORD)*cPal))
|
|
ulRet = 0;
|
|
}
|
|
|
|
VFREEMEM(pPalTmp);
|
|
}
|
|
}
|
|
|
|
FIXUP_THREAD_UMPDOBJS;
|
|
return ulRet;
|
|
}
|
|
|
|
ULONG APIENTRY NtGdiXLATEOBJ_iXlate(
|
|
IN XLATEOBJ *pxlo,
|
|
IN ULONG iColor
|
|
)
|
|
{
|
|
EXTRACT_THREAD_UMPDOBJS(0xffffffff);
|
|
|
|
ULONG ulRet = ((pxlo = pUMObjs->GetDDIOBJ(pxlo)) != NULL ? XLATEOBJ_iXlate(pxlo, iColor) : NULL);
|
|
|
|
FIXUP_THREAD_UMPDOBJS;
|
|
|
|
return ulRet;
|
|
}
|
|
|
|
BOOL APIENTRY NtGdiEngCheckAbort(
|
|
SURFOBJ *pso
|
|
)
|
|
|
|
{
|
|
EXTRACT_THREAD_UMPDOBJS(TRUE);
|
|
|
|
UMPDSURFOBJ umso(pso, pUMObjs);
|
|
pso = umso.pso();
|
|
|
|
BOOL bRet = pso ? EngCheckAbort(pso) : TRUE;
|
|
|
|
FIXUP_THREAD_UMPDOBJS;
|
|
return bRet;
|
|
}
|
|
|
|
//
|
|
// Ported from EngComputeGlyphSet with necessary changes
|
|
//
|
|
|
|
FD_GLYPHSET* APIENTRY NtGdiEngComputeGlyphSet(
|
|
INT nCodePage,
|
|
INT nFirstChar,
|
|
INT cChars
|
|
)
|
|
|
|
{
|
|
FD_GLYPHSET *pGlyphSet, *pGlyphSetTmp = NULL;
|
|
ULONG cjSize;
|
|
|
|
EXTRACT_THREAD_UMPDOBJS(NULL);
|
|
|
|
//
|
|
// Call kernel-mode EngComputeGlyphSet first and then copy
|
|
// the FD_GLYPHSET structure into a temporary user-mode buffer
|
|
//
|
|
|
|
if ((pGlyphSet = EngComputeGlyphSet(nCodePage, nFirstChar, cChars)) &&
|
|
(cjSize = pGlyphSet->cjThis) &&
|
|
(pGlyphSetTmp = (PFD_GLYPHSET) pUMObjs->AllocUserMem(cjSize)))
|
|
{
|
|
if (!GreCopyFD_GLYPHSET(pGlyphSetTmp, pGlyphSet, cjSize, TRUE))
|
|
pGlyphSetTmp = NULL;
|
|
}
|
|
|
|
//
|
|
// Free the kernel copy of the FD_GLYPHSET structure right away
|
|
//
|
|
|
|
if (pGlyphSet)
|
|
EngFreeMem(pGlyphSet);
|
|
|
|
FIXUP_THREAD_UMPDOBJS;
|
|
|
|
return (pGlyphSetTmp);
|
|
}
|
|
|
|
LONG APIENTRY NtGdiHT_Get8BPPFormatPalette(
|
|
LPPALETTEENTRY pPaletteEntry,
|
|
USHORT RedGamma,
|
|
USHORT GreenGamma,
|
|
USHORT BlueGamma
|
|
)
|
|
{
|
|
if (pPaletteEntry)
|
|
{
|
|
LPPALETTEENTRY pPal = NULL;
|
|
ULONG ulRet = 0;
|
|
ULONG c = HT_Get8BPPFormatPalette(NULL, RedGamma, GreenGamma, BlueGamma);
|
|
|
|
if (c)
|
|
{
|
|
if (BALLOC_OVERFLOW1(c, PALETTEENTRY))
|
|
return 0;
|
|
|
|
pPal = (LPPALETTEENTRY)PALLOCNOZ(c*sizeof(PALETTEENTRY), UMPD_MEMORY_TAG);
|
|
}
|
|
|
|
if (pPal)
|
|
{
|
|
ulRet = HT_Get8BPPFormatPalette(pPal, RedGamma, GreenGamma, BlueGamma);
|
|
|
|
if (!bSafeCopyBits(pPaletteEntry, pPal, c*sizeof(PALETTEENTRY)))
|
|
ulRet = 0;
|
|
|
|
VFREEMEM(pPal);
|
|
}
|
|
|
|
return ulRet;
|
|
}
|
|
else
|
|
return HT_Get8BPPFormatPalette(NULL, RedGamma, GreenGamma, BlueGamma);
|
|
|
|
}
|
|
|
|
|
|
LONG APIENTRY NtGdiHT_Get8BPPMaskPalette(
|
|
LPPALETTEENTRY pPaletteEntry,
|
|
BOOL Use8BPPMaskPal,
|
|
BYTE CMYMask,
|
|
USHORT RedGamma,
|
|
USHORT GreenGamma,
|
|
USHORT BlueGamma
|
|
)
|
|
{
|
|
LONG c = HT_Get8BPPMaskPalette(NULL, Use8BPPMaskPal, CMYMask, RedGamma, GreenGamma, BlueGamma);
|
|
|
|
if (pPaletteEntry) {
|
|
|
|
LPPALETTEENTRY pPal = NULL;
|
|
LONG cbPal;
|
|
|
|
if (((cbPal = c * sizeof(PALETTEENTRY)) > 0) &&
|
|
(!BALLOC_OVERFLOW1(c, PALETTEENTRY)) &&
|
|
(pPal = (LPPALETTEENTRY)PALLOCNOZ(cbPal, UMPD_MEMORY_TAG)) &&
|
|
(bSafeReadBits(pPal, pPaletteEntry, cbPal)) &&
|
|
(c = HT_Get8BPPMaskPalette(pPal,
|
|
Use8BPPMaskPal,
|
|
CMYMask,
|
|
RedGamma,
|
|
GreenGamma,
|
|
BlueGamma)) &&
|
|
(bSafeCopyBits(pPaletteEntry, pPal, cbPal))) {
|
|
|
|
NULL;
|
|
|
|
} else {
|
|
|
|
c = 0;
|
|
}
|
|
|
|
if (pPal) {
|
|
|
|
VFREEMEM(pPal);
|
|
}
|
|
}
|
|
|
|
return(c);
|
|
}
|
|
|
|
#endif // !_GDIPLUS_
|