Leaked source code of windows server 2003
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

/******************************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);
}