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.
770 lines
23 KiB
770 lines
23 KiB
/******************************Module*Header*******************************\
|
|
* Module Name: surfddi.cxx
|
|
*
|
|
* Surface DDI callback routines
|
|
*
|
|
* Created: 23-Aug-1990
|
|
* Author: Greg Veres [w-gregv]
|
|
*
|
|
* Copyright (c) 1990-1999 Microsoft Corporation
|
|
\**************************************************************************/
|
|
|
|
#include "precomp.hxx"
|
|
|
|
/******************************Public*Routine******************************\
|
|
* EngMarkBandingSurface
|
|
*
|
|
* DDI entry point to mark a surface as a banding surface meaning we should
|
|
* capture all output to it in a metafile.
|
|
*
|
|
* History:
|
|
* 10-Mar-1993 -by- Patrick Haluptzok patrickh
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
BOOL EngMarkBandingSurface(HSURF hsurf)
|
|
{
|
|
SURFREF so;
|
|
|
|
so.vAltCheckLockIgnoreStockBit(hsurf);
|
|
|
|
ASSERTGDI(so.bValid(), "ERROR EngMarkBandingSurfae invalid HSURF passed in\n");
|
|
|
|
so.ps->vSetBanding();
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* hbmCreateDriverSurface
|
|
*
|
|
* Common entry point for creating DDI surfaces.
|
|
*
|
|
* History:
|
|
* 11-Feb-1991 -by- Patrick Haluptzok patrickh
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
HBITMAP hbmCreateDriverSurface(ULONG iType, DHSURF dhsurf, SIZEL sizl, LONG lWidth,
|
|
ULONG iFormat, FLONG fl, PVOID pvBits)
|
|
{
|
|
DEVBITMAPINFO dbmi;
|
|
ULONG cjWidth = (ULONG) lWidth;
|
|
|
|
dbmi.iFormat = iFormat & ~UMPD_FLAG;
|
|
dbmi.cxBitmap = sizl.cx;
|
|
dbmi.cyBitmap = sizl.cy;
|
|
dbmi.hpal = (HPALETTE) 0;
|
|
dbmi.fl = fl;
|
|
|
|
//
|
|
// convert from bytes to pels if given a buffer and cjWidth. If either
|
|
// of these are set to 0 use what DIBMEMOBJ computes.
|
|
//
|
|
|
|
if ((pvBits) && (cjWidth))
|
|
{
|
|
switch (dbmi.iFormat)
|
|
{
|
|
case BMF_1BPP:
|
|
dbmi.cxBitmap = cjWidth * 8;
|
|
break;
|
|
|
|
case BMF_4BPP:
|
|
dbmi.cxBitmap = cjWidth * 2;
|
|
break;
|
|
|
|
case BMF_8BPP:
|
|
dbmi.cxBitmap = cjWidth;
|
|
break;
|
|
|
|
case BMF_16BPP:
|
|
dbmi.cxBitmap = cjWidth / 2;
|
|
break;
|
|
|
|
case BMF_24BPP:
|
|
dbmi.cxBitmap = cjWidth / 3;
|
|
break;
|
|
|
|
case BMF_32BPP:
|
|
dbmi.cxBitmap = cjWidth / 4;
|
|
break;
|
|
}
|
|
}
|
|
|
|
SURFMEM SurfDimo;
|
|
|
|
SurfDimo.bCreateDIB(&dbmi, pvBits);
|
|
|
|
if (!SurfDimo.bValid())
|
|
{
|
|
//
|
|
// Constructor logs error code.
|
|
//
|
|
|
|
return((HBITMAP) 0);
|
|
}
|
|
|
|
//
|
|
// We have to mark the surface with a special flag indicating it was
|
|
// created via EngCreateDeviceBitmap, instead of just looking for
|
|
// STYPE_DEVBITMAP, because EngModifySurface can change the type to
|
|
// STYPE_BITMAP yet we still want to cleanup the surface by calling
|
|
// DrvDeleteDeviceBitmap.
|
|
//
|
|
|
|
if (iType == STYPE_DEVBITMAP)
|
|
{
|
|
SurfDimo.ps->vSetEngCreateDeviceBitmap();
|
|
}
|
|
|
|
if (iType != STYPE_BITMAP)
|
|
{
|
|
SurfDimo.ps->lDelta(0);
|
|
SurfDimo.ps->pvScan0(NULL);
|
|
SurfDimo.ps->pvBits(NULL);
|
|
}
|
|
|
|
SurfDimo.ps->vSetDriverCreated();
|
|
SurfDimo.ps->sizl(sizl);
|
|
SurfDimo.ps->dhsurf(dhsurf);
|
|
SurfDimo.ps->iType(iType);
|
|
SurfDimo.vKeepIt();
|
|
|
|
//
|
|
// charge the surface from umpd driver against the process
|
|
// so we can clean it up afterwards
|
|
//
|
|
|
|
if (!(iFormat & UMPD_FLAG))
|
|
SurfDimo.vSetPID(OBJECT_OWNER_PUBLIC);
|
|
else
|
|
SurfDimo.ps->vSetUMPD();
|
|
|
|
return((HBITMAP) SurfDimo.ps->hsurf());
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* EngCreateBitmap
|
|
*
|
|
* DDI entry point to create a engine bitmap surface.
|
|
*
|
|
* History:
|
|
* 11-Feb-1991 -by- Patrick Haluptzok patrickh
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
HBITMAP EngCreateBitmap(SIZEL sizl, LONG lWidth, ULONG iFormat, FLONG fl, PVOID pvBits)
|
|
{
|
|
return(hbmCreateDriverSurface(STYPE_BITMAP, NULL, sizl, lWidth, iFormat,
|
|
fl, pvBits));
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* EngCreateDeviceBitmap
|
|
*
|
|
* DDI entry point to create device managed bitmap.
|
|
*
|
|
* History:
|
|
* 10-Mar-1993 -by- Patrick Haluptzok patrickh
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
HBITMAP EngCreateDeviceBitmap(DHSURF dhsurf, SIZEL sizl, ULONG iFormat)
|
|
{
|
|
return(hbmCreateDriverSurface(STYPE_DEVBITMAP, dhsurf, sizl, 0, iFormat,
|
|
0, (PVOID)UIntToPtr( 0xdeadbeef )));
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* EngCreateDeviceSurface
|
|
*
|
|
* DDI entry point to create device managed bitmap.
|
|
*
|
|
* History:
|
|
* 10-Mar-1993 -by- Patrick Haluptzok patrickh
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
HSURF EngCreateDeviceSurface(DHSURF dhsurf, SIZEL sizl, ULONG iFormat)
|
|
{
|
|
//
|
|
// [NT 4.0 compatible]
|
|
//
|
|
// EngCreateDeviceSurface in NT4, does not fail with invalid iFormat
|
|
// (especially 0, Adobe Acrobat 3.01 - PDFKD.DLL calls with 0 at least).
|
|
// So we replace the wrong data with something valid, here.
|
|
//
|
|
switch (iFormat & ~UMPD_FLAG)
|
|
{
|
|
case BMF_1BPP:
|
|
case BMF_4BPP:
|
|
case BMF_8BPP:
|
|
case BMF_16BPP:
|
|
case BMF_24BPP:
|
|
case BMF_32BPP:
|
|
break;
|
|
|
|
default:
|
|
//
|
|
// UMPD_FLAG should be preserved.
|
|
//
|
|
iFormat = (iFormat & UMPD_FLAG) | BMF_1BPP;
|
|
}
|
|
|
|
return((HSURF) hbmCreateDriverSurface(STYPE_DEVICE, dhsurf, sizl, 0,
|
|
iFormat, 0, (PVOID)UIntToPtr( 0xdeadbeef )));
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* EngDeleteSurface
|
|
*
|
|
* DDI entry point to delete a surface.
|
|
*
|
|
* History:
|
|
* Thu 12-Mar-1992 -by- Patrick Haluptzok [patrickh]
|
|
* change to bool return.
|
|
*
|
|
* 11-Feb-1991 -by- Patrick Haluptzok patrickh
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
BOOL EngDeleteSurface(HSURF hsurf)
|
|
{
|
|
BOOL bReturn = TRUE;
|
|
|
|
if (hsurf != 0)
|
|
{
|
|
bReturn = bDeleteSurface(hsurf);
|
|
}
|
|
|
|
ASSERTGDI(bReturn, "ERROR EngDeleteSurface failed");
|
|
|
|
return(bReturn);
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* EngLockSurface
|
|
*
|
|
* DDI entry point to lock down a surface handle.
|
|
*
|
|
* History:
|
|
* Thu 27-Aug-1992 -by- Patrick Haluptzok [patrickh]
|
|
* Remove SURFOBJ accelerator allocation.
|
|
*
|
|
* 11-Feb-1991 -by- Patrick Haluptzok patrickh
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
SURFOBJ *EngLockSurface(HSURF hsurf)
|
|
{
|
|
SURFREF so;
|
|
|
|
so.vAltCheckLockIgnoreStockBit(hsurf);
|
|
|
|
if (so.bValid())
|
|
{
|
|
so.vKeepIt();
|
|
return(so.pSurfobj());
|
|
}
|
|
else
|
|
{
|
|
WARNING("EngLockSurface failed to lock handle\n");
|
|
return((SURFOBJ *) NULL);
|
|
}
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* EngUnlockSurface
|
|
*
|
|
* DDI entry point to unlock a surface that has been locked
|
|
* with EngLockSurface.
|
|
*
|
|
* History:
|
|
* Thu 27-Aug-1992 -by- Patrick Haluptzok [patrickh]
|
|
* Remove SURFOBJ accelerator allocation.
|
|
*
|
|
* 11-Feb-1991 -by- Patrick Haluptzok patrickh
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
VOID EngUnlockSurface(SURFOBJ *pso)
|
|
{
|
|
if (pso != (SURFOBJ *) NULL)
|
|
{
|
|
|
|
SURFACE *ps = SURFOBJ_TO_SURFACE_NOT_NULL(pso);
|
|
|
|
if (ps == HmgReferenceCheckLock((HOBJ)pso->hsurf,SURF_TYPE,FALSE))
|
|
{
|
|
SURFREF su(pso);
|
|
|
|
su.vUnreference();
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
#if DBG
|
|
BOOL PanCopyBits(SURFOBJ*, SURFOBJ*, CLIPOBJ*, XLATEOBJ*, RECTL*, POINTL*);
|
|
|
|
VOID vAssertValidHookFlags(PDEVOBJ *pdo, SURFREF *pso)
|
|
{
|
|
FLONG flHooks;
|
|
flHooks = pso->ps->flags();
|
|
|
|
|
|
//
|
|
// Check to make sure we haven't disabled h/w accelerations and are now
|
|
// using the panning driver (unaccelerated driver).
|
|
//
|
|
|
|
if(PPFNDRV(*pdo, CopyBits)!=PanCopyBits) {
|
|
//
|
|
// Assert that the driver provides a routine entry point to match each
|
|
// Hooked flag.
|
|
//
|
|
// PPFNGET returns the driver routine if the appropriate flag is set.
|
|
// if the flag is set and the routine is NULL, we ASSERT.
|
|
//
|
|
// if the flag is not set, then PPFNGET returns the Eng routine, which
|
|
// better not be NULL, so we ASSERT if it is.
|
|
//
|
|
|
|
ASSERTGDI( (PPFNGET(*pdo, BitBlt, flHooks)),
|
|
"HOOK_BITBLT specified, but entry is NULL");
|
|
ASSERTGDI( (PPFNGET(*pdo, StretchBlt, flHooks)),
|
|
"HOOK_STRETCHBLT specified, but entry is NULL");
|
|
ASSERTGDI( (PPFNGET(*pdo, PlgBlt, flHooks)),
|
|
"HOOK_PLGBLT specified, but entry is NULL");
|
|
ASSERTGDI( (PPFNGET(*pdo, TextOut, flHooks)),
|
|
"HOOK_TEXTOUT specified, but entry is NULL");
|
|
ASSERTGDI( (PPFNGET(*pdo, Paint, flHooks)),
|
|
"HOOK_PAINT specified, but entry is NULL");
|
|
ASSERTGDI( (PPFNGET(*pdo, StrokePath, flHooks)),
|
|
"HOOK_STROKEPATH specified, but entry is NULL");
|
|
ASSERTGDI( (PPFNGET(*pdo, FillPath, flHooks)),
|
|
"HOOK_FILLPATH specified, but entry is NULL");
|
|
ASSERTGDI( (PPFNGET(*pdo, StrokeAndFillPath, flHooks)),
|
|
"HOOK_STROKEANDFILLPATH specified, but entry is NULL");
|
|
ASSERTGDI( (PPFNGET(*pdo, LineTo, flHooks)),
|
|
"HOOK_LINETO specified, but entry is NULL");
|
|
ASSERTGDI( (PPFNGET(*pdo, CopyBits, flHooks)),
|
|
"HOOK_COPYBITS specified, but entry is NULL");
|
|
ASSERTGDI( (PPFNGET(*pdo, StretchBltROP, flHooks)),
|
|
"HOOK_STRETCHBLTROP specified, but entry is NULL");
|
|
ASSERTGDI( (PPFNGET(*pdo, TransparentBlt, flHooks)),
|
|
"HOOK_TRANSPARENTBLT specified, but entry is NULL");
|
|
ASSERTGDI( (PPFNGET(*pdo, AlphaBlend, flHooks)),
|
|
"HOOK_ALPHABLEND specified, but entry is NULL");
|
|
ASSERTGDI( (PPFNGET(*pdo, GradientFill, flHooks)),
|
|
"HOOK_GRADIENTFILL specified, but entry is NULL");
|
|
|
|
ASSERTGDI( ((flHooks & HOOK_SYNCHRONIZE) == 0 ||
|
|
pdo->ppfn(INDEX_DrvSynchronize) != NULL ||
|
|
pdo->ppfn(INDEX_DrvSynchronizeSurface != NULL)),
|
|
"HOOK_SYNCHRONIZE specified, but appropriate driver function"
|
|
" (DrvSynchronize or DrvSynchronizeSurface) not available");
|
|
}
|
|
|
|
}
|
|
#endif
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* EngAssociateSurface *
|
|
* *
|
|
* DDI entry point for assigning a surface a palette, associating it with *
|
|
* a device. *
|
|
* *
|
|
* History: *
|
|
* Mon 27-Apr-1992 16:36:38 -by- Charles Whitmer [chuckwh] *
|
|
* Changed HPDEV to HDEV. *
|
|
* *
|
|
* Thu 12-Mar-1992 -by- Patrick Haluptzok [patrickh] *
|
|
* change to bool return *
|
|
* *
|
|
* Mon 01-Apr-1991 -by- Patrick Haluptzok [patrickh] *
|
|
* add pdev, dhpdev init, palette stuff *
|
|
* *
|
|
* 13-Feb-1991 -by- Patrick Haluptzok patrickh *
|
|
* Wrote it. *
|
|
\**************************************************************************/
|
|
|
|
BOOL EngAssociateSurface(HSURF hsurf, HDEV hdev, FLONG flHooks)
|
|
{
|
|
//
|
|
// Remove any obsolete HOOK_ flags, so that we can overload them for
|
|
// internal GDI purposes.
|
|
//
|
|
|
|
flHooks &= ~(HOOK_SYNCHRONIZEACCESS | HOOK_MOVEPANNING);
|
|
|
|
ASSERTGDI((flHooks & (~HOOK_FLAGS)) == 0, "ERROR driver set high flags");
|
|
|
|
//
|
|
// This call needs to associate this surface with the the HDEV given.
|
|
// We can't stick the palette in here because for palette managed devices
|
|
// the compatible bitmaps have a NULL palette. If we ever try and init
|
|
// the palettes here we need to be careful not to do it for compatible
|
|
// bitmaps on palette managed devices.
|
|
//
|
|
|
|
PDEVOBJ po(hdev);
|
|
if (!po.bValid())
|
|
{
|
|
WARNING("EngAssociateSurface: invalid PDEV passed in\n");
|
|
return FALSE;
|
|
}
|
|
|
|
SURFREF so;
|
|
|
|
so.vAltCheckLockIgnoreStockBit(hsurf);
|
|
|
|
if (!so.bValid())
|
|
{
|
|
WARNING("EngAssociateSurface: invalid SURF passed in\n");
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// EA Recovery support: If we are hooking the driver entry points for
|
|
// EA recovery, we need to store away the surface and associated
|
|
// LDEV so that when the DrvDeleteDeviceBitmap comes down, we can hook
|
|
// up the "real" driver entry point.
|
|
//
|
|
// NOTE: We only create this node if EA recovery is currently enabled, and
|
|
// DrvCreateDeviceBitmap (which will do the cleanup of the node) is present.
|
|
//
|
|
|
|
if (WatchdogIsFunctionHooked(po.pldev(), INDEX_DrvCreateDeviceBitmap)) {
|
|
|
|
if (so.ps->bEngCreateDeviceBitmap()) {
|
|
|
|
if (dhsurfAssociationIsNodeInList(so.ps->dhsurf(), hsurf) == FALSE) {
|
|
|
|
PDHSURF_ASSOCIATION_NODE Node = dhsurfAssociationCreateNode();
|
|
|
|
if (Node) {
|
|
|
|
Node->dhsurf = so.ps->dhsurf();
|
|
Node->hsurf = hsurf;
|
|
Node->pldev = po.pldev();
|
|
|
|
dhsurfAssociationInsertNode(Node);
|
|
|
|
} else {
|
|
|
|
WARNING("EngAssociateSurface: failed to create association node\n");
|
|
return(FALSE);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
so.ps->pwo((EWNDOBJ *)NULL);
|
|
so.ps->hdev(hdev);
|
|
so.ps->dhpdev(po.dhpdevNotDynamic()); // Since we're being called from
|
|
// the driver, we are implicitly
|
|
// holding a dynamic mode change
|
|
// lock, and so don't need to
|
|
// check it -- hence 'NotDynamic'
|
|
|
|
so.ps->flags(so.ps->flags() | flHooks);
|
|
|
|
#if DBG
|
|
vAssertValidHookFlags(&po, &so);
|
|
#endif
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* EngModifySurface
|
|
*
|
|
* DDI entry point for changing surface internals such as the type,
|
|
* bits pointers, and the hooked flags.
|
|
|
|
* 27-Apr-1998 -by- J. Andrew Goossen patrickh
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
BOOL EngModifySurface(
|
|
HSURF hsurf,
|
|
HDEV hdev,
|
|
FLONG flHooks,
|
|
FLONG flSurface,
|
|
DHSURF dhsurf,
|
|
VOID* pvScan0,
|
|
LONG lDelta,
|
|
VOID* pvReserved)
|
|
{
|
|
BOOL bRet = TRUE; // Assume success;
|
|
SURFREF so;
|
|
PDHSURF_ASSOCIATION_NODE Node = NULL;
|
|
|
|
PDEVOBJ po(hdev);
|
|
if (!po.bValid())
|
|
{
|
|
WARNING("EngModifySurface: invalid PDEV passed in");
|
|
return(FALSE);
|
|
}
|
|
|
|
so.vAltLockIgnoreStockBit(hsurf);
|
|
|
|
if (!so.bValid())
|
|
{
|
|
WARNING("EngModifySurface: invalid surface handle passed in");
|
|
return(FALSE);
|
|
}
|
|
|
|
if (pvReserved != NULL)
|
|
{
|
|
WARNING("EngModifySurface: pvReserved not NULL");
|
|
bRet = FALSE;
|
|
}
|
|
|
|
if (flSurface & ~(MS_NOTSYSTEMMEMORY | MS_SHAREDACCESS))
|
|
{
|
|
WARNING("EngModifySurface: invalid flSurface flag");
|
|
return(FALSE);
|
|
}
|
|
|
|
//
|
|
// Only surfaces that were created via EngCreateDeviceBitmap or
|
|
// EngCreateDeviceSurface are allowed to be modified. We do this
|
|
// primarily for two reasons:
|
|
//
|
|
// 1. This prevents the driver from modifying willy-nilly
|
|
// SURFOBJs that it sees;
|
|
// 2. If solves some problems with bDeleteSurface calling
|
|
// DrvDeleteDeviceBitmap (it was impossible to allow
|
|
// an STYPE_BITMAP surface to have DrvDeleteDeviceBitmap
|
|
// called, and still handle the DrvEnableSurface case
|
|
// where a driver created its primary surface using
|
|
// EngCreateSurface and modified the 'dhsurf' field --
|
|
// in this case DrvDeleteDeviceBitmap should not be called!
|
|
//
|
|
// Note that as a side effect of how we check for STYPE_DEVICE,
|
|
// primary surfaces should only ever be called with EngModifySurface
|
|
// once. Bitmap surfaces, however, can intentionally be modified by
|
|
// EngModifySurface any number times.
|
|
//
|
|
|
|
if (!(so.ps->bEngCreateDeviceBitmap()) && (so.ps->iType() != STYPE_DEVICE))
|
|
{
|
|
WARNING("EngModifySurface: surface not driver created");
|
|
bRet = FALSE;
|
|
}
|
|
|
|
if ((so.ps->hdev() != NULL) && (so.ps->hdev() != hdev))
|
|
{
|
|
WARNING("EngModifySurface: surface associated with different hdev");
|
|
bRet = FALSE;
|
|
}
|
|
|
|
//
|
|
// Remove any obsolete HOOK_ flags, so that we can overload them for
|
|
// internal GDI purposes.
|
|
//
|
|
|
|
flHooks &= ~(HOOK_SYNCHRONIZEACCESS | HOOK_MOVEPANNING);
|
|
|
|
ASSERTGDI((flHooks & (~HOOK_FLAGS)) == 0, "ERROR driver set high flags");
|
|
|
|
|
|
//
|
|
// WINBUG #254444 bhouse 12-14-2000 Allow drivers to change primary using EngModifySurface
|
|
// TODO: Additional code review of this change
|
|
// Allow drivers to change primary surface attributes so long as they
|
|
// are not changing the hooking flags and the PDEV is disabled.
|
|
//
|
|
|
|
|
|
if (so.ps->bPDEVSurface() && ((po.pSpriteState()->flOriginalSurfFlags & HOOK_FLAGS) != flHooks || !po.bDisabled()))
|
|
{
|
|
WARNING("EngModifySurface: can't modify PDEV surface once created");
|
|
bRet = FALSE;
|
|
}
|
|
|
|
//
|
|
// EA Recovery support: If we are hooking the driver entry points for
|
|
// EA recovery, we need to store away the surface and associated
|
|
// LDEV so that when the DrvDeleteDeviceBitmap comes down, we can hook
|
|
// up the "real" driver entry point.
|
|
//
|
|
//
|
|
// NOTE: We only create this node if EA recovery is currently enabled, and
|
|
// DrvCreateDeviceBitmap (which will do the cleanup of the node) is present.
|
|
//
|
|
|
|
if (WatchdogIsFunctionHooked(po.pldev(), INDEX_DrvCreateDeviceBitmap)) {
|
|
|
|
if (so.ps->bEngCreateDeviceBitmap()) {
|
|
|
|
if (dhsurfAssociationIsNodeInList(dhsurf, hsurf) == FALSE) {
|
|
|
|
Node = dhsurfAssociationCreateNode();
|
|
|
|
if (Node) {
|
|
|
|
Node->dhsurf = dhsurf;
|
|
Node->hsurf = hsurf;
|
|
Node->pldev = po.pldev();
|
|
|
|
} else {
|
|
|
|
WARNING("EngAssociateSurface: failed to create association node\n");
|
|
bRet = FALSE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// First, try changing the surface's type as appropriate:
|
|
//
|
|
|
|
if ((pvScan0 == NULL) || (lDelta == 0))
|
|
{
|
|
//
|
|
// Make the surface opaque, assuming they've hooked the minimum
|
|
// number of calls to allow an opaque surface.
|
|
//
|
|
|
|
if ((flHooks & (HOOK_TEXTOUT | HOOK_BITBLT | HOOK_STROKEPATH))
|
|
!= (HOOK_TEXTOUT | HOOK_BITBLT | HOOK_STROKEPATH))
|
|
{
|
|
WARNING("EngModifySurface: opaque surfaces must hook textout, bitblt, strokepath");
|
|
bRet = FALSE;
|
|
}
|
|
|
|
if (!(flSurface & MS_NOTSYSTEMMEMORY))
|
|
{
|
|
WARNING("EngModifySurface: why have opaque surface if system memory?");
|
|
bRet = FALSE;
|
|
}
|
|
|
|
if (dhsurf == NULL)
|
|
{
|
|
WARNING("EngModifySurface: opaque types must have a dhsurf");
|
|
bRet = FALSE;
|
|
}
|
|
|
|
//
|
|
// If all systems are go, convert to an opaque surface:
|
|
//
|
|
|
|
if (bRet)
|
|
{
|
|
so.ps->pvScan0(NULL);
|
|
so.ps->pvBits(NULL);
|
|
so.ps->lDelta(0);
|
|
|
|
//
|
|
// We're making the surface opaque, and STYPE_DEVICE surfaces should
|
|
// remain STYPE_DEVICE to denote the primary surface, and not become
|
|
// STYPE_DEVBITMAP.
|
|
//
|
|
|
|
if (so.ps->iType() != STYPE_DEVICE)
|
|
{
|
|
so.ps->iType(STYPE_DEVBITMAP);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ((flSurface & MS_NOTSYSTEMMEMORY) && !(flHooks & HOOK_SYNCHRONIZE))
|
|
{
|
|
WARNING("EngModifySurface: VRAM non-opaque surfaces must hook synchronize");
|
|
bRet = FALSE;
|
|
}
|
|
|
|
//
|
|
// If all systems are go, convert to a GDI-managed surface:
|
|
//
|
|
|
|
if (bRet)
|
|
{
|
|
so.ps->pvScan0(pvScan0);
|
|
so.ps->lDelta(lDelta);
|
|
so.ps->iType(STYPE_BITMAP);
|
|
|
|
if (lDelta > 0)
|
|
{
|
|
so.ps->pvBits(pvScan0);
|
|
so.ps->fjBitmap(so.ps->fjBitmap() | BMF_TOPDOWN);
|
|
}
|
|
else
|
|
{
|
|
so.ps->pvBits((VOID*) ((BYTE*) pvScan0
|
|
+ (so.ps->sizl().cy - 1) * lDelta));
|
|
so.ps->fjBitmap(so.ps->fjBitmap() & ~BMF_TOPDOWN);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// If we were successful in changing the type, update some common fields:
|
|
//
|
|
|
|
if (bRet)
|
|
{
|
|
if (flSurface & MS_NOTSYSTEMMEMORY)
|
|
{
|
|
so.ps->fjBitmap(so.ps->fjBitmap() | BMF_NOTSYSMEM);
|
|
}
|
|
else
|
|
{
|
|
so.ps->fjBitmap(so.ps->fjBitmap() & ~BMF_NOTSYSMEM);
|
|
}
|
|
|
|
if (flSurface & MS_SHAREDACCESS)
|
|
{
|
|
so.ps->vSetShareAccess();
|
|
}
|
|
else
|
|
{
|
|
so.ps->vClearShareAccess();
|
|
}
|
|
|
|
so.ps->dhsurf(dhsurf);
|
|
so.ps->pwo((EWNDOBJ *)NULL);
|
|
so.ps->hdev(hdev);
|
|
so.ps->dhpdev(po.dhpdev());
|
|
|
|
so.ps->flags((so.ps->flags() & ~HOOK_FLAGS) | flHooks);
|
|
// Replace the old hooked flags
|
|
// with the new ones
|
|
|
|
#if DBG
|
|
vAssertValidHookFlags(&po, &so);
|
|
#endif
|
|
|
|
//
|
|
// If we created a Node for EA recovery purposes, then insert the
|
|
// node into our list now that we know this function will succeed.
|
|
//
|
|
|
|
if (Node) {
|
|
dhsurfAssociationInsertNode(Node);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// We are failing. Thus if we created an association node above,
|
|
// we should clean that up.
|
|
//
|
|
|
|
if (Node) {
|
|
AssociationDeleteNode(Node);
|
|
Node = NULL;
|
|
}
|
|
|
|
WARNING("EngModifySurface: failed");
|
|
}
|
|
|
|
return(bRet);
|
|
}
|