|
|
/******************************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_
|