Windows NT 4.0 source code leak
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.
 
 
 
 
 
 

657 lines
18 KiB

/******************************Module*Header*******************************\
* Module Name: surfeng.cxx
*
* Internal surface routines
*
* Created: 13-May-1991 12:53:31
* Author: Patrick Haluptzok patrickh
*
* Copyright (c) 1991 Microsoft Corporation
\**************************************************************************/
#include "precomp.hxx"
/******************************Public*Routine******************************\
* GreSetBitmapOwner
*
* Sets the bitmap owner.
*
\**************************************************************************/
BOOL
GreSetBitmapOwner(
HBITMAP hbm,
W32PID lPid
)
{
BOOL bRet = FALSE;
SURFREF so((HSURF)hbm);
if (so.bValid())
{
if (!(so.ps->bDIBSection() && (lPid == OBJECT_OWNER_PUBLIC)))
{
bRet = HmgSetOwner((HOBJ)hbm,lPid,SURF_TYPE);
}
else
{
WARNING ("GreSetBitmapOnwer - Setting a DIBSECTION to PUBLIC\n");
}
}
else
{
WARNING1("GreSetBitmapOnwer - invalid surfobj\n");
}
return(bRet);
}
/******************************Public*Routine******************************\
* bInitBMOBJ
*
* Initializes the default bitmap.
*
* History:
* 14-Apr-1991 -by- Patrick Haluptzok patrickh
* Wrote it.
\**************************************************************************/
BOOL bInitBMOBJ()
{
HBITMAP hbmTemp = GreCreateBitmap(1, 1, 1, 1, (LPBYTE) NULL);
if (hbmTemp == (HBITMAP) 0)
{
WARNING("Failed to create default bitmap\n");
return(FALSE);
}
SURFREF so((HSURF)hbmTemp);
ASSERTGDI(so.bValid(), "ERROR it created but isn't lockable STOCKOBJ_BITMAP");
ASSERTGDI(so.ps->ppal() == ppalMono, "ERROR the default bitmap has no ppalMono");
so.vSetPID(OBJECT_OWNER_PUBLIC);
bSetStockObject(hbmTemp,PRIV_STOCK_BITMAP);
so.ps->hsurf((HANDLE)((DWORD)hbmTemp | GDISTOCKOBJ));
SURFACE::pdibDefault = so.ps;
return(TRUE);
}
/******************************Public*Routine******************************\
* BOOL bDeleteSurface(HSURF)
*
* Delete the surface object
*
* History:
* Sun 14-Apr-1991 -by- Patrick Haluptzok [patrickh]
* Wrote it.
\**************************************************************************/
BOOL bDeleteSurface(HSURF hsurf)
{
SURFREF so(hsurf);
return(so.bDeleteSurface());
}
/******************************Public*Routine******************************\
* GreSelectBitmap
*
* Select the bitmap into a DC
*
* History:
* Wed 28-Aug-1991 -by- Patrick Haluptzok [patrickh]
* update it, make palette aware.
*
* Mon 13-May-1991 -by- Patrick Haluptzok [patrickh]
* Wrote it.
\**************************************************************************/
HBITMAP GreSelectBitmap(HDC hdc, HBITMAP hsurf)
{
HSURF hsurfReturn = (HSURF) 0;
BOOL bDelete = FALSE;
//
// Grab multi-lock so noone can select or delete it.
//
MLOCKOBJ mlo;
//
// Lock bitmap
//
SURFREF SurfBoNew;
SurfBoNew.vMultiLock((HSURF) hsurf);
MDCOBJ dco(hdc);
if (dco.bValid() && SurfBoNew.bValid())
{
PSURFACE pSurfNew = SurfBoNew.ps;
ASSERTGDI(DIFFHANDLE(hsurf,STOCKOBJ_BITMAP) ||
(pSurfNew->cRef() == 0) , "ERROR STOCKOBJ_BITMAP cRef != 0");
PDEVOBJ po(dco.hdev());
PPALETTE ppalSrc;
if ((dco.dctp() == DCTYPE_MEMORY) &&
((pSurfNew->cRef() == 0) || SAMEHANDLE(pSurfNew->hdc(),dco.hdc())) &&
(bIsCompatible(&ppalSrc, pSurfNew->ppal(),pSurfNew, dco.hdev())))
{
if (pSurfNew->ppal() != ppalSrc)
{
pSurfNew->flags(pSurfNew->flags() | PALETTE_SELECT_SET);
pSurfNew->ppal(ppalSrc);
}
SURFACE *pSurfBoOld = dco.pSurfaceEff();
hsurfReturn = pSurfBoOld->hsurf();
if (DIFFHANDLE((HSURF) hsurf, hsurfReturn))
{
if (pSurfNew->bIsDefault())
{
dco.pdc->pSurface((SURFACE *) NULL);
}
else
{
dco.pdc->pSurface((SURFACE *) pSurfNew);
}
dco.pdc->sizl(pSurfNew->sizl());
dco.pdc->ulDirtyAdd(DIRTY_BRUSHES);
//
// Lower the reference count on the old handle
//
if (!pSurfBoOld->bIsDefault())
{
pSurfBoOld->vDec_cRef();
if (pSurfBoOld->cRef() == 0)
{
//
// Remove reference to device palette if it has one.
//
if (pSurfBoOld->flags() & PALETTE_SELECT_SET)
pSurfBoOld->ppal(NULL);
pSurfBoOld->flags(pSurfBoOld->flags() & ~PALETTE_SELECT_SET);
}
}
//
// Device Format Bitmaps hooked by the driver must always
// have devlock synchronization.
//
// Other device-dependent bitmaps must have devlock
// synchronization if they can be affected by dynamic mode
// changes, because they may have to be converted on-the-fly
// to DIBs.
//
dco.bSynchronizeAccess(
(pSurfNew->flags() & HOOK_SYNCHRONIZEACCESS) ||
(pSurfNew->bDeviceDependentBitmap() && po.bDisplayPDEV()));
//
// Put the relevant DC information into the surface as long as it's not
// the default surface.
//
if (!pSurfNew->bIsDefault())
{
pSurfNew->hdc(dco.hdc());
pSurfNew->vInc_cRef();
pSurfNew->hdev(dco.hdev());
pSurfNew->dhpdev(dco.dhpdev());
}
//
// set DIBSection flag in DC
//
dco.pdc->vDIBSection(pSurfNew->bDIBSection());
mlo.vDisable();
dco.pdc->bSetDefaultRegion();
if (pSurfBoOld->bLazyDelete())
{
pSurfBoOld->bDeleteSurface();
hsurfReturn = (HSURF)STOCKOBJ_BITMAP;
}
}
}
else
{
WARNING1("GreSelectBitmap failed selection, bitmap doesn't fit into DC\n");
}
}
else
{
#if DBG
if (dco.bValid())
{
WARNING1("GreSelectBitmap given invalid bitmap\n");
}
else
{
WARNING1("GreSelectBitmap given invalid DC\n");
}
#endif
}
return((HBITMAP) hsurfReturn);
}
/******************************Public*Routine******************************\
* hbmCreateClone
*
* Creates an engine managed clone of a bitmap.
*
* History:
* Tue 17-May-1994 -by- Patrick Haluptzok [patrickh]
* Synchronize the call if it's a DFB that needs synching.
*
* 19-Jun-1991 -by- Patrick Haluptzok patrickh
* Wrote it.
\**************************************************************************/
HBITMAP hbmCreateClone(SURFACE *pSurfSrc, ULONG cx, ULONG cy)
{
ASSERTGDI(pSurfSrc != NULL, "ERROR hbmCreateClone invalid src");
ASSERTGDI((pSurfSrc->iType() == STYPE_BITMAP) ||
(pSurfSrc->iType() == STYPE_DEVBITMAP), "ERROR hbmCreateClone src type");
DEVBITMAPINFO dbmi;
dbmi.iFormat = pSurfSrc->iFormat();
if ((cx == 0) || (cy == 0))
{
dbmi.cxBitmap = pSurfSrc->sizl().cx;
dbmi.cyBitmap = pSurfSrc->sizl().cy;
}
else
{
ASSERTGDI(cx <= LONG_MAX, "hbmCreateClone: cx too large\n");
dbmi.cxBitmap = min(pSurfSrc->sizl().cx,(LONG)cx);
ASSERTGDI(cy <= LONG_MAX, "hbmCreateClone: cy too large\n");
dbmi.cyBitmap = min(pSurfSrc->sizl().cy,(LONG)cy);
}
dbmi.hpal = (HPALETTE) 0;
if (pSurfSrc->ppal() != NULL)
{
dbmi.hpal = (HPALETTE) pSurfSrc->ppal()->hGet();
}
dbmi.fl = BMF_TOPDOWN;
HBITMAP hbmReturn = (HBITMAP) 0;
SURFMEM SurfDimo;
if (SurfDimo.bCreateDIB(&dbmi, NULL))
{
POINTL ptlSrc;
ptlSrc.x = 0;
ptlSrc.y = 0;
RECTL rclDst;
rclDst.left = 0;
rclDst.right = dbmi.cxBitmap;
rclDst.top = 0;
rclDst.bottom = dbmi.cyBitmap;
//
// Have EngBitBlt initialize the bitmap.
//
PDEVICE_LOCK pdevLock = NULL;
if (pSurfSrc->flags() & HOOK_SYNCHRONIZEACCESS)
{
PDEVOBJ po(pSurfSrc->hdev());
ASSERTGDI(po.bValid(), "PDEV invalid");
pdevLock = po.pDevLock();
VACQUIREDEVLOCK(pdevLock);
}
if (EngCopyBits( SurfDimo.pSurfobj(), // Destination surfobj
pSurfSrc->pSurfobj(), // Source surfobj.
(CLIPOBJ *) NULL, // Clip object.
&xloIdent, // Palette translation object.
&rclDst, // Destination rectangle.
&ptlSrc
)
)
{
SurfDimo.vKeepIt();
hbmReturn = (HBITMAP) SurfDimo.ps->hsurf();
}
else
{
WARNING("ERROR hbmCreateClone failed EngBitBlt\n");
}
if (pdevLock)
{
VRELEASEDEVLOCK(pdevLock);
}
}
else
{
WARNING("ERROR hbmCreateClone failed DIB allocation\n");
}
return(hbmReturn);
}
/******************************Public*Routine******************************\
* NtGdiGetDCforBitmap
*
* Get the DC that the bitmap is selected into
*
* History:
* 12-12-94 -by- Lingyun Wang[lingyunw]
* Wrote it.
\**************************************************************************/
HDC NtGdiGetDCforBitmap(HBITMAP hsurf)
{
HDC hdcReturn = 0;
SURFREF so((HSURF) hsurf);
if (so.bValid())
{
hdcReturn = so.ps->hdc();
}
return(hdcReturn);
}
/******************************Public*Routine******************************\
* GreMakeInfoDC()
*
* This routine is used to take a printer DC and temporarily make it a
* Metafile DC for spooled printing. This way it can be associated with
* an enhanced metafile. During this period, it should look and act just
* like an info DC.
*
* bSet determines if it should be set into the INFO DC state or restored
* to the Direct state.
*
* History:
* 04-Jan-1995 -by- Eric Kutter [erick]
* Wrote it.
\**************************************************************************/
BOOL GreMakeInfoDC(
HDC hdc,
BOOL bSet)
{
ASSERTGDI(LO_TYPE(hdc) == LO_ALTDC_TYPE,"GreMakeInfoDC - not alt type\n");
BOOL bRet = FALSE;
XDCOBJ dco( hdc );
if (dco.bValid())
{
bRet = dco.pdc->bMakeInfoDC(bSet);
dco.vUnlockFast();
}
return(bRet);
}
/******************************Private*Routine*****************************\
* BOOL pConvertDfbSurfaceToDib
*
* Converts a compatible bitmap into an engine managed bitmap. Note that
* if the bitmap is currently selected into a DC, bConvertDfbDcToDib should
* be called.
*
* The devlock must be already be held.
*
* History:
* Wed 5-May-1994 -by- Tom Zakrajsek [tomzak]
* Wrote it (with lots of help from PatrickH and EricK).
\*************************************************************************/
SURFACE* pConvertDfbSurfaceToDib
(
HDEV hdev,
SURFACE *pSurfOld,
LONG ExpectedShareCount
)
{
SURFACE *pSurfNew;
SURFACE *pSurfRet;
pSurfRet = NULL;
ASSERTGDI((pSurfOld != NULL),
"pConvertDfbSurfaceToDib: pSurf attached to the DC is NULL\n");
ASSERTGDI((pSurfOld->iType() == STYPE_DEVBITMAP),
"pConvertDfbSurfaceToDib: Src was not a compatible bitmap\n");
//
// Create a DIB (dimoCvt) with the same height,width,
// and BPP as the DEVBITMAP attached to the DC and
// then replace the DEVBITMAP with the DIB
//
SURFMEM dimoCvt;
DEVBITMAPINFO dbmi;
ERECTL ercl(0, 0, pSurfOld->sizl().cx, pSurfOld->sizl().cy);
PDEVOBJ po(hdev);
//
// Figure out what format the engine should use by looking at the
// size of palette. This is a clone from CreateCompatibleBitmap().
//
dbmi.iFormat = po.iDitherFormat();
dbmi.cxBitmap = pSurfOld->sizl().cx;
dbmi.cyBitmap = pSurfOld->sizl().cy;
dbmi.hpal = 0;
dbmi.fl = BMF_TOPDOWN;
if (dimoCvt.bCreateDIB(&dbmi, NULL))
{
pSurfNew = dimoCvt.ps;
//
// Fill in other necessary fields
//
ASSERTGDI(pSurfOld->hdev() == hdev, "hdev's don't match");
pSurfNew->hdev(hdev);
//
// Copy the area as big as the bitmap
//
if ((*PPFNGET(po, CopyBits, pSurfOld->flags()))
(
dimoCvt.pSurfobj(), // destination surface
pSurfOld->pSurfobj(), // source surface
(CLIPOBJ *)NULL, // clip object
&xloIdent, // palette translation object
(RECTL *) &ercl, // destination rectangle
(POINTL *) &ercl // source origin
))
{
MLOCKOBJ mlo;
LONG SurfTargShareCount;
SurfTargShareCount = HmgQueryAltLock((HOBJ)pSurfOld->hsurf());
if (SurfTargShareCount == ExpectedShareCount)
{
if (HmgSwapLockedHandleContents((HOBJ)pSurfOld->hsurf(),
SurfTargShareCount,
(HOBJ)pSurfNew->hsurf(),
HmgQueryAltLock((HOBJ)pSurfNew->hsurf()),
SURF_TYPE))
{
//
// Swap necessary fields between the bitmaps
// hsurf, hdc, cRef, hpalHint, sizlDim, ppal, SurfFlags
//
HSURF hsurfTemp = pSurfOld->hsurf();
pSurfOld->hsurf(pSurfNew->hsurf());
pSurfNew->hsurf(hsurfTemp);
HDC hdcTemp = pSurfOld->hdc();
pSurfOld->hdc(pSurfNew->hdc());
pSurfNew->hdc(hdcTemp);
ULONG cRefTemp = pSurfOld->cRef();
pSurfOld->cRef(pSurfNew->cRef());
pSurfNew->cRef(cRefTemp);
HPALETTE hpalTemp = pSurfOld->hpalHint();
pSurfOld->hpalHint(pSurfNew->hpalHint());
pSurfNew->hpalHint(hpalTemp);
SIZEL sizlTemp = pSurfOld->sizlDim();
pSurfOld->sizlDim(pSurfNew->sizlDim());
pSurfNew->sizlDim(sizlTemp);
PPALETTE ppalTemp = pSurfOld->ppal();
pSurfOld->ppal(pSurfNew->ppal());
pSurfNew->ppal(ppalTemp);
FLONG flagsTemp = pSurfOld->flags() & SURF_FLAGS;
pSurfOld->flags(pSurfOld->flags() & ~SURF_FLAGS);
pSurfNew->flags(pSurfNew->flags() | flagsTemp);
ASSERTGDI(pSurfNew->bDeviceDependentBitmap(),
"Expected DDB_SURFACE flag to be transferred.");
//
// Destroy the DFB
//
mlo.vDisable();
pSurfOld->bDeleteSurface();
dimoCvt.vKeepIt();
dimoCvt.ps = NULL;
pSurfRet = pSurfNew;
}
else
{
WARNING("pConvertDfbSurfaceToDib failed to swap bitmap handles\n");
}
}
else
{
WARNING("pConvertDfbSurfaceToDib someone else is holding a lock\n");
}
}
else
{
WARNING("pConvertDfbSurfaceToDib failed copying DFB to DIB\n");
}
}
return(pSurfRet);
}
/******************************Private*Routine*****************************\
* BOOL bConvertDfbDcToDib
*
* Converts a compatible bitmap that is currently selected into a DC
* into an engine managed bitmap.
*
* The Devlock must already be held. Some sort of lock must also be held
* to prevent SaveDC/RestoreDC operations from occuring -- either via an
* exclusive DC lock or some other lock.
*
* History:
* Wed 5-May-1994 -by- Tom Zakrajsek [tomzak]
* Wrote it (with lot's of help from PatrickH and EricK).
\*************************************************************************/
BOOL bConvertDfbDcToDib
(
XDCOBJ * pdco
)
{
SURFACE *pSurfOld;
SURFACE *pSurfNew;
ASSERTDEVLOCK(pdco->pdc);
pSurfOld = pdco->pSurface();
pSurfNew = pConvertDfbSurfaceToDib(pdco->hdev(),
pSurfOld,
pSurfOld->cRef());
if (pSurfNew)
{
//
// Make sure that the surface pointers in any EBRUSHOBJ's get
// updated, by ensuring that vInitBrush() gets called the next
// time any brush is used in this DC.
//
pdco->pdc->flbrushAdd(DIRTY_BRUSHES);
//
// Replace the pSurf reference in the DCLEVEL
//
pdco->pdc->pSurface(pSurfNew);
//
// Walk the saved DC chain
//
LONG lNumLeft = pdco->lSaveDepth();
HDC hdcSave = pdco->hdcSave();
while (lNumLeft > 1)
{
MDCOBJA dcoTmp(hdcSave);
//
// Replace all references to pSurfOld with references to pSurfNew
//
if (dcoTmp.pSurface() == pSurfOld)
{
dcoTmp.pdc->pSurface(pSurfNew);
}
lNumLeft = dcoTmp.lSaveDepth();
hdcSave = dcoTmp.hdcSave();
}
}
return(pSurfNew != NULL);
}