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.
 
 
 
 
 
 

2071 lines
58 KiB

/******************************Module*Header*******************************\
* Module Name: dcgdi.cxx
*
* APIs for GDI DC component
*
* Created: 13-Aug-1990 00:15:53
* Author: Donald Sidoroff [donalds]
*
* Copyright (c) 1990-1999 Microsoft Corporation
\**************************************************************************/
#include "precomp.hxx"
BOOL bSavePath(XDCOBJ& dco, LONG lSave);
BOOL bSaveRegion(DCOBJ&, LONG);
VOID vRestorePath(XDCOBJ& dco, LONG lSave);
VOID vRestoreRegion(DCOBJ&, LONG);
typedef BOOL (*SFN)(DCOBJ&, LONG); // Save function type
typedef VOID (*RFN)(DCOBJ&, LONG); // Restore function type
/******************************Public*Routine******************************\
* bDeleteDCInternal
*
* bForce - This is set to TRUE when user calls through GreDeleteDC and
* FALSE when the app calls through th client server window
*
* API entry point to delete a DC.
*
* History:
* Thu 12-Sep-1991 -by- Patrick Haluptzok [patrickh]
* clean it up, query User for deletability, cascade if's for code size.
*
* Fri 12-Jul-1991 -by- Patrick Haluptzok [patrickh]
* added deletion of regions
*
* 18-Jun-1991 -by- Patrick Haluptzok patrickh
* Wrote it.
\**************************************************************************/
BOOL
bDeleteDCInternal(
HDC hdc,
BOOL bForce,
BOOL bProcessCleanup)
{
BOOL bReturn = FALSE;
// Lock it down, since this is an API lock no apps can get at it. We just
// have to worry about USER having it Alt-locked now.
DCOBJ dco(hdc);
if (dco.bValid())
{
// We can do a cleanDC without affecting USER.
dco.bCleanDC();
// Check if User has marked the DC as undeletable or bForce is set.
// bForce should only be set when user asks us to delete the dc.
if (bForce || dco.bIsDeleteable())
{
// free client attr
if (!bProcessCleanup)
{
GreFreeDCAttributes(hdc);
}
// ASSERTGDI(dco.bIsDeleteable(), "User is freeing an undeletable DC");
// Decrement the reference count on the brushes in the old DC.
// we do not dec the ref cnt of a brush from the client side
// since sync brush never inc the ref cnt
DEC_SHARE_REF_CNT_LAZY0(dco.pdc->pbrushFill());
DEC_SHARE_REF_CNT_LAZY0(dco.pdc->pbrushLine());
// We now need to do the same thing for the selected font
DEC_SHARE_REF_CNT_LAZY_DEL_LOGFONT(dco.pdc->plfntNew());
// And then color space, too
DEC_SHARE_REF_CNT_LAZY_DEL_COLORSPACE(dco.pdc->pColorSpace());
// Ok we are golden now. User has no holds on this DC.
// Remember our PDEV.
PDEVOBJ po(dco.hdev());
dco.pdc->vReleaseVis();
dco.pdc->vReleaseRao();
if (dco.pdc->prgnRao())
{
dco.pdc->prgnRao()->vDeleteREGION();
}
// Free the memory for the DC. We don't even need to do this
// under a multi-lock because we have an API lock so no other
// App threads can come in and User has said that it is deleteable
// and they are the only dudes who could get us with an Alt-Lock.
// we may still hold a dc lock when the user mode printer driver
// abnomally terminates. Ignore the counts.
if (!po.bUMPD())
{
ASSERTGDI(HmgQueryLock((HOBJ)hdc) == 1, "bDeleteDC cLock != 1");
ASSERTGDI(HmgQueryAltLock((HOBJ)hdc) == 0, "bDeleteDC cAltLock != 0");
}
// delete DC from handle manager.
dco.bDeleteDC(bProcessCleanup);
// Remove the reference to the PDEV.
po.vUnreferencePdev(bProcessCleanup ? CLEANUP_PROCESS
: CLEANUP_NONE);
// Return success.
bReturn = TRUE;
}
else
{
// User now maps CreateDC -> GetDC so that all DC's get clipped
// to the same Desktop. We now have to check here and give User
// a chance to clean it up.
dco.vUnlock();
if (UserReleaseDC(hdc))
{
bReturn = TRUE;
}
else
{
WARNING("FAILED to delete because it is a NON-DeletableDC\n");
}
}
}
else
{
// Some other thread has it locked down so fail.
SAVE_ERROR_CODE(ERROR_BUSY);
}
return(bReturn);
}
BOOL
GreDeleteDC(
HDC hdc)
{
return(bDeleteDCInternal(hdc,TRUE,FALSE));
}
/******************************Public*Routine******************************\
* BOOL GreRestoreDC(hdc, lDC)
*
* Restore the DC.
*
* History:
* Mon 15-Jul-1991 -by- Patrick Haluptzok [patrickh]
* bug fix, delete the DC when done with it.
*
* Tue 18-Jun-1991 -by- Patrick Haluptzok [patrickh]
* added the brush, palette, pen, and bitmap cases.
*
* 13-Aug-1990 -by- Donald Sidoroff [donalds]
* Wrote it.
\**************************************************************************/
BOOL GreRestoreDC(HDC hdc,int lDC)
{
DCOBJ dco(hdc); // Lock the DC
BOOL bRet = TRUE;
if (!dco.bValid())
{
SAVE_ERROR_CODE(ERROR_INVALID_HANDLE);
bRet = FALSE;
}
else
{
// !! What the heck is this SYNC_DRAWING_ATTRS doing here?
SYNC_DRAWING_ATTRS(dco.pdc);
if (lDC < 0)
lDC += (int)dco.lSaveDepth();
if ((lDC < 1) || (lDC >= dco.lSaveDepth()))
{
SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
bRet = FALSE;
}
else
{
PDEVOBJ po(dco.hdev());
// Acquire the devlock here to protect against dynamic mode changes
// that affect the device palette. This also protects us if the
// bitmap which selected in DC, is a Device Format Bitmap that is
// owned by the display driver.
DEVLOCKOBJ dlo(po);
// Acquire the semaphore palette to be symmetrical with GreSaveDC
// and to protect the dynamic mode change code as it walks all
// the DC's, so that its changes don't get wiped out by the
// vCopyTo we're about to do.
SEMOBJ semo(ghsemPalette);
// if we are printing using a TempInfoDC, save it. Since there is only one
// of these that does not sit in the dclevel, we save and restore this state
// accross save/restoreDC
BOOL bTempInfoDC = dco.pdc->bTempInfoDC();
if (bTempInfoDC)
dco.pdc->bMakeInfoDC(FALSE);
// Remember current mapping mode.
ULONG ulMapModeDC = dco.pdc->ulMapMode();
do
{
// Decrement the reference count on the brushes in the old DC.
// We do not DEC the ref cnt of a brush from the client side
// since sync brush never INCs the ref cnt
DEC_SHARE_REF_CNT_LAZY0(dco.pdc->pbrushFill());
DEC_SHARE_REF_CNT_LAZY0(dco.pdc->pbrushLine());
// same thing for currently selected font:
DEC_SHARE_REF_CNT_LAZY_DEL_LOGFONT(dco.pdc->plfntNew());
// same thing for currently selected color space:
DEC_SHARE_REF_CNT_LAZY_DEL_COLORSPACE(dco.pdc->pColorSpace());
// Restore Regions and Paths.
vRestoreRegion(dco, dco.lSaveDepth() - 1);
vRestorePath(dco, dco.lSaveDepth() - 1);
// Restore the bitmaps if necesary.
if (dco.dctp() == DCTYPE_MEMORY)
{
hbmSelectBitmap(hdc, STOCKOBJ_BITMAP, TRUE);
}
// Bug #223129: We need to get a lock on the saved DC even when the process
// has reached its handle quota (this is OK because the saved DC is about to
// be deleted anyway). This is accomplished using the vLockAllOwners method
// of the DCOBJ.
DCOBJ dcoSaved;
dcoSaved.vLockAllOwners(dco.hdcSave());
ASSERTGDI(dcoSaved.bValid(),"GreRestoreDC(): dcoSaved is invalid\n");
// Select the palette in if necessary. This will put the palette back in
// the DC chain.
if (dco.hpal() != dcoSaved.hpal())
{
GreSelectPalette((HDC)hdc, (HPALETTE)dcoSaved.ppal()->hGet(), TRUE);
}
else
{
// hpals are equal:
//
// ResizePalette could have changed the ppal associated with the
// hpal, in this case fix the ppal
if (dco.ppal() != dcoSaved.ppal())
{
EPALOBJ palRestore((HPALETTE)dco.hpal());
if (dco.ppal() != palRestore.ppalGet())
{
RIP("GRE RestoreDC - hpal and ppal in invalid state");
}
// fix ppal in dcoSaved
dcoSaved.pdc->ppal(palRestore.ppalGet());
}
}
// Decrement its reference count if it's not the default palette. We
// inced it while it's in a saved DC level to prevent it from being deleted.
if (dcoSaved.ppal() != ppalDefault)
{
XEPALOBJ palTemp(dcoSaved.ppal());
palTemp.vDec_cRef();
}
// Update the DC with saved information, then delete the saved level.
dcoSaved.pdc->vCopyTo(dco);
dcoSaved.bDeleteDC();
} while (lDC < dco.lSaveDepth());
// if mapping mode has been changed, invalidate xform.
if (ulMapModeDC != dco.pdc->ulMapMode())
dco.pdc->vXformChange(TRUE);
// if we are printing using a TempInfoDC, restore it
if (bTempInfoDC)
dco.pdc->bMakeInfoDC(TRUE);
// Assume Rao has been made dirty by the above work.
dco.pdc->vReleaseRao();
dco.pdc->vUpdate_VisRect(dco.pdc->prgnVis());
// Assume the brushes, charset, color space and color transform are dirty.
dco.ulDirtyAdd(DIRTY_BRUSHES|DIRTY_CHARSET|DIRTY_COLORSPACE|DIRTY_COLORTRANSFORM);
if (dco.dctp() == DCTYPE_MEMORY)
{
dco.pdc->bSetDefaultRegion();
}
// Correctly set the bit indicating whether or not we need to
// grab the Devlock before drawing
SURFACE *pSurfCurrent = dco.pSurface();
//
// Note that this condition should match that of GreSelectBitmap
// for the memory DC case:
//
if (dco.bDisplay() ||
((dco.dctp() == DCTYPE_MEMORY) &&
(pSurfCurrent != NULL) &&
(
(pSurfCurrent->bUseDevlock()) ||
(pSurfCurrent->bDeviceDependentBitmap() && po.bDisplayPDEV())
)
)
)
{
dco.bSynchronizeAccess(TRUE);
dco.bShareAccess(pSurfCurrent->bShareAccess());
}
else
{
dco.bSynchronizeAccess(FALSE);
}
// Update ptlFillOrigin accelerator
dco.pdc->vCalcFillOrigin();
}
}
return(bRet);
}
/*********************************Class************************************\
* class SAVEOBJ
*
* This is just a call to a save/restore function pair disguised to look
* like a memory object. The restore will happen automagically when the
* scope is exitted, unless told not to do so.
*
* Note:
* This is used only by GreSaveDC
*
* History:
* 23-Apr-1991 -by- Donald Sidoroff [donalds]
* Wrote it.
\**************************************************************************/
class SAVEOBJ /* svo */
{
private:
LONG lLevel;
BOOL bSave;
DCOBJ *pdco;
RFN rfn; // Restore function
public:
SAVEOBJ(DCOBJ& dco, LONG lLevel_, SFN sfn, RFN rfn_)
{
pdco = &dco;
lLevel = lLevel_;
rfn = rfn_;
bSave = (*sfn)(dco, lLevel_ + 1);
}
~SAVEOBJ()
{
if (bSave)
(*rfn)(*pdco, lLevel);
}
BOOL bValid() { return(bSave); }
VOID vKeepIt() { bSave = FALSE; }
};
/*********************************Class************************************\
* class DCMODOBJ
*
* This class modifies the given DC. It will undo the modification, unless
* told to keep it.
*
* Note:
* This is used only by GreSaveDC
*
* History:
* 23-Apr-1991 -by- Donald Sidoroff [donalds]
* Wrote it.
\**************************************************************************/
class DCMODOBJ /* dcmod */
{
private:
DCOBJ *pdco;
HDC hdcSaveOld;
public:
DCMODOBJ(DCOBJ& dco, HDC hdcSave)
{
pdco = &dco;
hdcSaveOld = dco.hdcSave();
dco.pdc->hdcSave(hdcSave);
}
~DCMODOBJ()
{
if (pdco != (DCOBJ *) NULL)
pdco->pdc->hdcSave(hdcSaveOld);
}
VOID vKeepIt() { pdco = (DCOBJ *) NULL; }
};
/******************************Public*Routine******************************\
* int GreSaveDC(hdc)
*
* Save the DC.
*
* History:
* Tue 25-Jun-1991 -by- Patrick Haluptzok [patrickh]
* add saving bitmaps, palettes.
*
* 13-Aug-1990 -by- Donald Sidoroff [donalds]
* Wrote it.
\**************************************************************************/
int GreSaveDC(HDC hdc)
{
DCOBJ dco(hdc); // Lock down the DC
LONG lSave;
int iRet = 0;
if (!dco.bValid())
{
SAVE_ERROR_CODE(ERROR_INVALID_HANDLE);
}
else
{
SYNC_DRAWING_ATTRS(dco.pdc);
PDEVOBJ po(dco.hdev());
// Acquire the devlock here to protect against dynamic mode changes
// that affect the device palette. This also protects us if the
// bitmap which selected in DC, is a Device Format Bitmap that is
// owned by the display driver.
DEVLOCKOBJ dlo(po);
// We must grab the semaphore now so that ResizePalette doesn't
// change the ppal in the DC before the copy is added to the list
// off the palette. Also grab it to prevent the dynamic mode
// changing code from falling over when it traverses saved DCs.
SEMOBJ semo(ghsemPalette);
// if we are printing using a TempInfoDC, save it. Since there is only one
// of these that does not sit in the dclevel, we save and restore this state
// accross save/restoreDC
BOOL bTempInfoDC = dco.pdc->bTempInfoDC();
if (bTempInfoDC)
dco.pdc->bMakeInfoDC(FALSE);
{
DCMEMOBJ dcmo(dco); // Allocate RAM and copy the DC
if (!dcmo.bValid())
{
SAVE_ERROR_CODE(ERROR_NOT_ENOUGH_MEMORY);
}
else
{
DCMODOBJ dcmod(dco, dcmo.hdc());
SAVEOBJ svoPath(dco, dcmo.lSaveDepth(), (SFN)bSavePath, (RFN)vRestorePath);
if (svoPath.bValid())
{
SAVEOBJ svoRgn(dco, dcmo.lSaveDepth(), bSaveRegion, vRestoreRegion);
if (svoRgn.bValid())
{
// we are done with the objects so we can now set the owner to none
// so this thing can't be deleted.
if (!GreSetDCOwner(dcmo.hdc(),OBJECT_OWNER_NONE))
{
WARNING("GreSaveDC - couldn't set owner\n");
}
else
{
// At this point we are golden. No more errors can occur,
// so we mark all the things we've allocated as permanent.
svoRgn.vKeepIt();
svoPath.vKeepIt();
dcmod.vKeepIt();
dcmo.vKeepIt();
// Inc the surface ref count if appropriate
if (dcmo.pSurface() != (SURFACE *) NULL)
{
if ((!dcmo.pSurface()->bPDEVSurface()) && (!dcmo.pSurface()->bRedirection()))
{
dcmo.pSurface()->vInc_cRef();
}
}
// Increment the reference count on the brushes we saved.
// No need to check ownership, since these are already
// selected in
INC_SHARE_REF_CNT(dco.pdc->pbrushFill());
INC_SHARE_REF_CNT(dco.pdc->pbrushLine());
// inc ref count for the font selected in the dc
INC_SHARE_REF_CNT(dco.pdc->plfntNew());
// int ref count for the color space selected in the dc
INC_SHARE_REF_CNT(dco.pdc->pColorSpace());
// Take care of the palette.
// Increment its reference count if it's not the default palette. We
// inc it while it's in a saved DC level to prevent it from being deleted.
if (dco.ppal() != ppalDefault)
{
XEPALOBJ palTemp(dco.ppal());
ASSERTGDI(palTemp.bValid(), "ERROR SaveDC not valid palette");
palTemp.vInc_cRef();
}
// Increment and return the save level of the original DC.
lSave = dco.lSaveDepth();
dco.pdc->lIncSaveDepth();
iRet = (int)lSave;
} // GreSetDCOwner
} //
} // ~SAVEOBJ svoRgn
} // ~DCMODOBJ dcmod
} // ~DCMEMOBJ dcmo
// if we are printing using a TempInfoDC, restore it
if (bTempInfoDC)
dco.pdc->bMakeInfoDC(TRUE);
}
return(iRet);
}
/******************************Public*Routine******************************\
* BOOL GreSetDCOrg(hdc,x,y,prlc)
*
* Set the origin and optionally the window area of the DC.
*
* History:
* 19-Oct-1996 -by- J. Andrew Goossen [andrewgo]
* Wrote it.
\**************************************************************************/
BOOL GreSetDCOrg(HDC hdc,LONG x,LONG y,PRECTL prcl)
{
BOOL bRet = FALSE;
DCOBJA dco(hdc);
ASSERTDEVLOCK(dco.pdc);
if (dco.bValid())
{
bRet = TRUE;
dco.eptlOrigin().x = x;
dco.eptlOrigin().y = y;
dco.pdc->vCalcFillOrigin();
if (prcl != NULL)
{
dco.erclWindow() = *(ERECTL *) prcl;
}
}
return(bRet);
}
/******************************Public*Routine******************************\
* BOOL GreGetDCOrg(hdc,pptl)
*
* Get the origin of the DC.
*
* History:
* Sun 02-Jan-1994 -by- Patrick Haluptzok [patrickh]
* smaller and faster
*
* 13-Aug-1990 -by- Donald Sidoroff [donalds]
* Wrote it.
\**************************************************************************/
BOOL GreGetDCOrg(HDC hdc,LPPOINT pptl)
{
return(GreGetDCPoint(hdc,DCPT_DCORG,(PPOINTL)pptl));
}
/******************************Public*Routine******************************\
* BOOL GreGetDCOrgEx(hdc,ppt,prcl)
*
* History:
* 12-Dec-1997 -by- Vadim Gorokhovsky [vadimg]
* Wrote it.
\**************************************************************************/
BOOL GreGetDCOrgEx(HDC hdc,PPOINT ppt,PRECT prc)
{
DCOBJA dco(hdc);
if (dco.bValid())
{
*(ERECTL *)prc = dco.erclWindow();
return(GreGetDCPoint(hdc,DCPT_DCORG,(PPOINTL)ppt));
}
return(FALSE);
}
/******************************Public*Routine******************************\
* BOOL GreGetBounds(hdc, prcl, fl)
*
* Return the current bounds information and reset the bounding area.
*
* WARNING: USER MUST HOLD THE DEVICE LOCK BEFORE CALLING THIS ROUTINE
*
* History:
* 28-Jul-1991 -by- Donald Sidoroff [donalds]
* Wrote it.
\**************************************************************************/
BOOL GreGetBounds(HDC hdc, LPRECT prcl, DWORD fl)
{
DCOBJA doa(hdc);
ERECTL erclScreen;
BOOL bEmpty;
if (!doa.bValid())
{
bEmpty = TRUE; // bEmpty == TRUE is the error condition
}
else
{
if (fl & GGB_ENABLE_WINMGR)
{
doa.fsSet(DC_ACCUM_WMGR);
}
else if (fl & GGB_DISABLE_WINMGR)
{
doa.fsClr(DC_ACCUM_WMGR);
}
// Get the state of the bounds rectangle
bEmpty = (doa.erclBounds().bEmpty() ||
doa.erclBounds().bWrapped());
if (!bEmpty)
{
if (prcl != (LPRECT) NULL)
{
erclScreen = doa.erclBounds();
erclScreen += doa.eptlOrigin();
*prcl = *((LPRECT) &erclScreen);
}
// Force it to be empty
doa.erclBounds().left = POS_INFINITY;
doa.erclBounds().top = POS_INFINITY;
doa.erclBounds().right = NEG_INFINITY;
doa.erclBounds().bottom = NEG_INFINITY;
}
}
return(!bEmpty);
}
/******************************Public*Routine******************************\
* BOOL GreGetBoundsRect(hdc, prcl, fl)
*
* Return the current bounds info.
*
* History:
* Thu 27-May-1993 -by- Patrick Haluptzok [patrickh]
* Change to exclusive lock, not a special User call.
*
* 06-Apr-1992 -by- Donald Sidoroff [donalds]
* Wrote it.
\**************************************************************************/
DWORD GreGetBoundsRect(HDC hdc, LPRECT prcl, DWORD fl)
{
DCOBJ dco(hdc);
DWORD dwRet = DCB_SET;
if (!dco.bValid())
{
dwRet = 0;
}
else
{
ERECTL *percl;
if (fl & DCB_WINDOWMGR)
{
if (dco.erclBounds().bWrapped())
{
dwRet = DCB_RESET;
}
else
{
percl = &dco.erclBounds();
*prcl = *((LPRECT) percl);
}
}
else
{
if (dco.erclBoundsApp().bWrapped())
{
dwRet = DCB_RESET;
}
else
{
DEVLOCKOBJ dlo(dco);
if (!dlo.bValid())
{
dwRet = dco.bFullScreen() ? DCB_RESET : 0;
}
else
{
RGNOBJ ro(dco.prgnEffRao());
ERECTL ercl;
ro.vGet_rcl(&ercl);
ercl -= dco.eptlOrigin();
percl = &dco.erclBoundsApp();
prcl->left = MAX(percl->left, ercl.left);
prcl->right = MIN(percl->right, ercl.right);
prcl->top = MAX(percl->top, ercl.top);
prcl->bottom = MIN(percl->bottom, ercl.bottom);
EXFORMOBJ exoDtoW(dco, DEVICE_TO_WORLD);
if (!exoDtoW.bValid())
{
dwRet = 0;
}
else if (!exoDtoW.bRotation())
{
if (!exoDtoW.bXform((POINTL *) prcl, 2))
dwRet = 0;
}
else
{
POINTL apt[4];
*((RECT *)apt) = *prcl;
apt[2].x = prcl->left;
apt[2].y = prcl->bottom;
apt[3].x = prcl->right;
apt[3].y = prcl->top;
if (!exoDtoW.bXform(apt, 4))
{
dwRet = 0;
}
else
{
prcl->left = MIN4(apt[0].x,apt[1].x,apt[2].x,apt[3].x);
prcl->right = MAX4(apt[0].x,apt[1].x,apt[2].x,apt[3].x);
prcl->top = MIN4(apt[0].y,apt[1].y,apt[2].y,apt[3].y);
prcl->bottom = MAX4(apt[0].y,apt[1].y,apt[2].y,apt[3].y);
}
}
}
}
}
if ((dwRet == DCB_SET) && (fl & DCB_RESET))
{
percl->left = percl->top = POS_INFINITY;
percl->right = percl->bottom = NEG_INFINITY;
}
}
return(dwRet);
}
/******************************Public*Routine******************************\
* BOOL GreSetBoundsRect(hdc, prcl, fl)
*
* Set the current bounds info.
*
* History:
* Thu 27-May-1993 -by- Patrick Haluptzok [patrickh]
* Make it exclusive lock, this is a general purpose API
*
* 06-Apr-1992 -by- Donald Sidoroff [donalds]
* Wrote it.
\**************************************************************************/
DWORD GreSetBoundsRect(HDC hdc, LPRECT prcl, DWORD fl)
{
DWORD dwState = 0;
DCOBJ dco(hdc);
if (dco.bValid())
{
ERECTL *percl;
FSHORT fsEnable;
BOOL bEnabled;
BOOL bError = FALSE;
if (fl & DCB_WINDOWMGR)
{
percl = &dco.erclBounds();
fsEnable = DC_ACCUM_WMGR;
bEnabled = dco.bAccum();
}
else
{
percl = &dco.erclBoundsApp();
fsEnable = DC_ACCUM_APP;
bEnabled = dco.bAccumApp();
}
dwState = (fl & DCB_WINDOWMGR);
if (percl->bWrapped())
dwState |= DCB_RESET;
else
dwState |= DCB_SET;
if (bEnabled)
dwState |= DCB_ENABLE;
else
dwState |= DCB_DISABLE;
// Reset the rectangle if we've been asked to do so.
if (fl & DCB_RESET)
{
percl->left = percl->top = POS_INFINITY;
percl->right = percl->bottom = NEG_INFINITY;
}
// If we are accumulating, do the union.
if (fl & DCB_ACCUMULATE)
{
ASSERTGDI(prcl,"GreSetBoundsRect - DCB_ACCUMULATE with no prcl\n");
// Convert the incoming rectangle to DEVICE coordinates.
if (!(fl & DCB_WINDOWMGR))
{
EXFORMOBJ exo(dco, WORLD_TO_DEVICE);
if (!exo.bRotation())
{
if (!exo.bXform((POINTL *)prcl, 2))
bError = TRUE;
}
else
{
POINTL apt[4];
*((RECT *)apt) = *prcl;
apt[2].x = prcl->left;
apt[2].y = prcl->bottom;
apt[3].x = prcl->right;
apt[3].y = prcl->top;
if (!exo.bXform(apt, 4))
{
bError = TRUE;
}
else
{
prcl->left = MIN4(apt[0].x,apt[1].x,apt[2].x,apt[3].x);
prcl->right = MAX4(apt[0].x,apt[1].x,apt[2].x,apt[3].x);
prcl->top = MIN4(apt[0].y,apt[1].y,apt[2].y,apt[3].y);
prcl->bottom = MAX4(apt[0].y,apt[1].y,apt[2].y,apt[3].y);
}
}
}
*percl |= *((ERECTL *) prcl);
}
if (!bError)
{
// Enable or Disable accumulation
if (fl & DCB_ENABLE)
dco.fsSet(fsEnable);
if (fl & DCB_DISABLE)
dco.fsClr(fsEnable);
}
else
{
dwState = 0;
}
}
return(dwState);
}
/******************************Public*Routine******************************\
* GreMarkUndeletableDC
*
* Private API for USER.
*
* Mark a DC as undeletable. This must be called before the hdc is ever
* passed out so that we are guranteed the lock will not fail because a
* app is using it.
*
* History:
* 13-Sep-1991 -by- Patrick Haluptzok patrickh
* Wrote it.
\**************************************************************************/
VOID GreMarkUndeletableDC(HDC hdc)
{
XDCOBJ dco(hdc);
if (dco.bValid())
{
dco.vMakeUndeletable();
dco.vUnlockFast();
}
else
{
WARNING("ERROR User gives Gdi invalid DC");
}
}
/******************************Public*Routine******************************\
* GreMarkDeletableDC
*
* Private API for USER.
*
* This can be called anytime by USER to make the DC deletable.
*
* History:
* 13-Sep-1991 -by- Patrick Haluptzok patrickh
* Wrote it.
\**************************************************************************/
VOID GreMarkDeletableDC(HDC hdc)
{
XDCOBJ dcoa;
dcoa.vAltLock(hdc);
if (dcoa.bValid())
{
dcoa.vMakeDeletable();
dcoa.vAltUnlockFast();
}
else
{
WARNING("ERROR User gives Gdi invalid DC");
}
}
/******************************Public*Routine******************************\
* HFONT GreGetHFONT(HDC)
*
* This is a private entry point user by USER when they pass the
* DRAWITEMSTRUC message to the client to get the current handle.
* This is done because they may have set the font on the server
* side, in which case the client does not know about it.
*
* History:
* Tue 28-Dec-1993 -by- Patrick Haluptzok [patrickh]
* smaller and faster
*
* 16-Sep-1991 - by - Eric Kutter [erick]
* Wrote it.
\**************************************************************************/
HFONT GreGetHFONT(HDC hdc)
{
XDCOBJ dco(hdc);
HFONT hfont = (HFONT) 0;
if (dco.bValid())
{
hfont = (HFONT) dco.pdc->hlfntNew();
dco.vUnlockFast();
}
return(hfont);
}
/******************************Public*Routine******************************\
* GreCancelDC()
*
* History:
* 14-Apr-1992 -by- - by - Eric Kutter [erick]
* Wrote it.
\**************************************************************************/
BOOL GreCancelDC(HDC hdc)
{
BOOL bReturn;
//
// The handle manager lock prevents the DC from being deleted while
// we've got the DC alt-locked, and it also prevents the dynamic
// mode change code from updating pSurface() while we're looking at
// it.
//
MLOCKFAST mlo;
XDCOBJ dco;
dco.vAltCheckLock(hdc);
if (bReturn = dco.bValid())
{
SURFACE *pSurface = dco.pSurface();
if (pSurface != (SURFACE *) NULL)
pSurface->vSetAbort();
dco.vAltUnlockFast();
}
#if DBG
else
{
WARNING("GreCancelDC passed invalid DC\n");
}
#endif
return(bReturn);
}
/******************************Public*Routine******************************\
* VOID GreMarkDCUnreadable(hdc)
*
* Mark a DC as secure.
*
* History:
* 13-Aug-1990 -by- Donald Sidoroff [donalds]
* Wrote it.
\**************************************************************************/
VOID APIENTRY GreMarkDCUnreadable(HDC hdc)
{
XDCOBJ dco;
dco.vAltLock(hdc);
MLOCKFAST mlo; // Protect pSurface() access
if (dco.bValid())
{
ASSERTGDI(dco.dctp() == DCTYPE_DIRECT, "Non-screen DC marked as secure!\n");
dco.pSurface()->flags(dco.pSurface()->flags() | UNREADABLE_SURFACE);
PDEVOBJ pdo(dco.hdev());
SPRITESTATE *pState = pdo.pSpriteState();
pState->flOriginalSurfFlags |= UNREADABLE_SURFACE;
pState->flSpriteSurfFlags |= UNREADABLE_SURFACE;
dco.vAltUnlockFast();
}
else
{
WARNING("Invalid DC passed to GreMarkDCUnreadable\n");
}
}
DWORD dwGetFontLanguageInfo(XDCOBJ& dco);
/******************************Public*Routine******************************\
* BOOL NtGdiGetDCDword(hdc,uint)
*
* Query DC to get a particular DWORD of info.
*
* History:
* 9-Nov-1994 -by- Gerrit van Wingerden [gerritv]
* Wrote it.
\**************************************************************************/
#if DBG
ULONG acGetDCDword[DDW_MAX] = {0};
#endif
BOOL NtGdiGetDCDword( HDC hdc, UINT u, DWORD *pdwResult )
{
BOOL bResult = TRUE;
DWORD dwTmp;
XDCOBJ dco( hdc );
if(!dco.bValid())
{
WARNING("Invalid DC or offset passed to GreGetDCDword\n");
bResult = FALSE;
}
else
{
switch( u )
{
case DDW_JOURNAL:
dwTmp = !(dco.flGraphicsCaps() & GCAPS_DONTJOURNAL);
break;
case DDW_RELABS:
dwTmp = dco.pdc->lRelAbs();
break;
case DDW_BREAKEXTRA :
dwTmp = dco.pdc->lBreakExtra();
break;
case DDW_CBREAK:
dwTmp = dco.pdc->cBreak();
break;
case DDW_MAPMODE:
dwTmp = dco.ulMapMode();
break;
case DDW_ARCDIRECTION:
if (MIRRORED_DC(dco.pdc))
dwTmp = dco.pdc->bClockwise() ? AD_COUNTERCLOCKWISE : AD_CLOCKWISE;
else
dwTmp = dco.pdc->bClockwise() ? AD_CLOCKWISE : AD_COUNTERCLOCKWISE;
break;
case DDW_SAVEDEPTH:
dwTmp = dco.lSaveDepth();
break;
case DDW_FONTLANGUAGEINFO:
dwTmp = dwGetFontLanguageInfo(dco);
break;
case DDW_ISMEMDC:
dwTmp = ( dco.dctp() == DCTYPE_MEMORY );
break;
default:
WARNING("Illegal offset passed to GreGetDCDword\n");
bResult = FALSE;
break;
}
if (bResult)
{
#if DBG
acGetDCDword[u]++;
#endif
_try
{
ProbeAndWriteUlong(pdwResult, dwTmp);
}
_except(EXCEPTION_EXECUTE_HANDLER)
{
// SetLastError(GetExceptionCode());
bResult = FALSE;
}
}
dco.vUnlockFast();
}
return(bResult);
}
/******************************Public*Routine******************************\
* BOOL NtGdiGetAndSetDCDword(hdc,uint,DWORD,DWORD*)
*
* Set a particular value in a DC DWORD and return the old value. Note this
* function should not be incorperated with GetDCDword because all the values
* will eventually be place in an array eliminating the need for a switch
* statement. This function, however, will need to do valiation specific
* to each particular attribute so we wil still need a switch statement.
*
* History:
* 9-Nov-1994 -by- Gerrit van Wingerden [gerritv]
* Wrote it.
\**************************************************************************/
#if DBG
ULONG acSetDCDword[GASDDW_MAX] = {0};
#endif
BOOL NtGdiGetAndSetDCDword( HDC hdc, UINT u, DWORD dwIn, DWORD *pdwResult )
{
BOOL bResult = TRUE;
DWORD dwTmp = ERROR;
XDCOBJ dco( hdc );
if(!dco.bValid())
{
WARNING("Invalid DC passed to GreGetAndSetDCDword\n");
if (u == GASDDW_TEXTCHARACTEREXTRA)
{
_try
{
ProbeAndWriteUlong(pdwResult, 0x80000000);
}
_except(EXCEPTION_EXECUTE_HANDLER)
{
// SetLastError(GetExceptionCode());
}
}
return FALSE;
}
switch( u )
{
case GASDDW_COPYCOUNT:
dwTmp = dco.ulCopyCount();
dco.ulCopyCount( dwIn );
break;
case GASDDW_EPSPRINTESCCALLED:
dwTmp = (DWORD) dco.bEpsPrintingEscape();
dco.vClearEpsPrintingEscape();
break;
case GASDDW_RELABS:
dwTmp = dco.pdc->lRelAbs();
dco.pdc->lRelAbs(dwIn);
break;
case GASDDW_SELECTFONT:
WARNING("should not be here\n");
/*
dwTmp = (DWORD) dco.pdc->hlfntNew();
dco.pdc->hlfntNew((HLFONT)dwIn);
if ((HLFONT)dwIn != dco.pdc->hlfntCur())
dco.ulDirtyAdd(DIRTY_CHARSET);
*/
break;
case GASDDW_MAPPERFLAGS:
if( dwIn & (~ASPECT_FILTERING) )
{
WARNING1("gdisrv!GreSetMapperFlags(): unknown flag\n");
SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
dwTmp = GDI_ERROR;
}
else
{
dwTmp = dco.pdc->flFontMapper();
dco.pdc->flFontMapper((DWORD) dwIn);
}
break;
case GASDDW_MAPMODE:
{
DWORD dwResult = dco.ulMapMode();
if (dwResult != dwIn)
{
dwResult = dco.pdc->iSetMapMode(dwIn);
}
dwTmp = dwResult;
}
break;
case GASDDW_ARCDIRECTION:
if (MIRRORED_DC(dco.pdc)) {
dwTmp = dco.pdc->bClockwise() ? AD_COUNTERCLOCKWISE : AD_CLOCKWISE;
if (dwIn == AD_CLOCKWISE)
dco.pdc->vClearClockwise();
else if (dwIn == AD_COUNTERCLOCKWISE)
dco.pdc->vSetClockwise();
else
{
SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
dwTmp = ERROR;
}
}
else
{
dwTmp = dco.pdc->bClockwise() ? AD_CLOCKWISE : AD_COUNTERCLOCKWISE;
if (dwIn == AD_CLOCKWISE)
dco.pdc->vSetClockwise();
else if (dwIn == AD_COUNTERCLOCKWISE)
dco.pdc->vClearClockwise();
else
{
SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
dwTmp = ERROR;
}
}
break;
default:
WARNING("Illegal offset passed to GreGetAndSetDCDword\n");
bResult = FALSE;
break;
}
if (bResult)
{
#if DBG
acSetDCDword[u]++;
#endif
_try
{
ProbeAndWriteUlong(pdwResult, dwTmp);
}
_except(EXCEPTION_EXECUTE_HANDLER)
{
// SetLastError(GetExceptionCode());
bResult = FALSE;
}
}
dco.vUnlockFast();
return(bResult);
}
/******************************Public*Routine******************************\
* GreGetDCPoint()
*
* History:
* 30-Nov-1994 -by- Eric Kutter [erick]
* Wrote it.
\**************************************************************************/
BOOL GreGetDCPoint(
HDC hdc,
UINT u,
PPOINTL pptOut
)
{
BOOL bResult = TRUE;
XDCOBJ dco(hdc);
if( dco.bValid() )
{
switch(u)
{
case DCPT_VPEXT:
if (dco.pdc->bPageExtentsChanged() && (dco.ulMapMode() == MM_ISOTROPIC))
dco.pdc->vMakeIso();
dco.pdc->vGet_szlViewportExt((PSIZEL)pptOut);
break;
case DCPT_WNDEXT:
dco.pdc->vGet_szlWindowExt((PSIZEL)pptOut);
if (MIRRORED_DC(dco.pdc))
pptOut->x = -pptOut->x;
break;
case DCPT_VPORG:
dco.pdc->vGet_ptlViewportOrg(pptOut);
if (MIRRORED_DC(dco.pdc))
pptOut->x = -pptOut->x;
break;
case DCPT_WNDORG:
dco.pdc->vGet_ptlWindowOrg(pptOut);
pptOut->x = dco.pdc->pDCAttr->lWindowOrgx;
break;
case DCPT_ASPECTRATIOFILTER:
bResult = GreGetAspectRatioFilter(hdc,(LPSIZE)pptOut);
break;
case DCPT_DCORG:
*pptOut = dco.eptlOrigin();
break;
default:
RIP("Illegal offset passed to GreGetAndSetDCPoint\n");
bResult = FALSE;
}
dco.vUnlockFast();
}
else
{
WARNING("Invalid DC passed to GreGetDCPoint\n");
bResult = FALSE;
}
return(bResult);
}
/******************************Public*Routine******************************\
* NtGdiGetDCObject()
*
* History:
* 01-Dec-1994 -by- Eric Kutter [erick]
* Wrote it.
\**************************************************************************/
HANDLE NtGdiGetDCObject(HDC hdc, int itype)
{
HANDLE hReturn = (HANDLE) 0;
//
// Try to lock the DC. If we fail, we just return failure.
//
XDCOBJ dco(hdc);
if (dco.bValid())
{
SYNC_DRAWING_ATTRS(dco.pdc);
//
// The DC is locked.
//
switch (itype)
{
case LO_BRUSH_TYPE:
hReturn = (HANDLE)(dco.pdc->pbrushFill())->hGet();
break;
case LO_PEN_TYPE:
case LO_EXTPEN_TYPE:
hReturn = (HANDLE)(dco.pdc->pbrushLine())->hGet();
break;
case LO_FONT_TYPE:
hReturn = (HANDLE) dco.pdc->hlfntNew();
break;
case LO_PALETTE_TYPE:
hReturn = (HANDLE) dco.hpal();
break;
case LO_BITMAP_TYPE:
{
//
// Acquire the Devlock because we're groveling
// in the DC's surface pointer, which could otherwise
// be changed asynchronously by the dyanmic mode change
// code.
//
DEVLOCKOBJ dlo;
dlo.vLockNoDrawing(dco);
hReturn = (HANDLE) dco.pSurfaceEff()->hsurf();
break;
}
default: break;
}
dco.vUnlockFast();
}
return(hReturn);
}
/******************************Public*Routine******************************\
* GreCleanDC(hdc)
*
* Set up some stuff up in the DC
*
* History:
* 20-Apr-1995 -by- Andre Vachon [andreva]
\**************************************************************************/
BOOL
GreCleanDC(
HDC hdc
)
{
DCOBJ dco(hdc);
if (dco.bValid())
{
if (dco.bCleanDC())
{
return(TRUE);
}
#if DBG
PVOID pv1, pv2;
RtlGetCallersAddress(&pv1,&pv2);
DbgPrint("GreCleanDC failed to lock DC (%p), (c1 = %p, c2 = %p)\n",
hdc, pv1, pv2);
#endif
}
return(FALSE);
}
/******************************Public*Routine******************************\
* GreSetDCOwner
*
* Set the owner of the DC
*
* if the owner is set to OBJECTOWNER_NONE, this dc will not be useable
* until GreSetDCOwner is called to explicitly give the dc to someone else.
*
* Arguments:
*
* hdc - DC to modify
* lPid - one of OBJECT_OWNER_NONE,OBJECT_OWNER_PUBLIC or
* OBJECT_OWNER_CURRENT
*
* Return Value:
*
* TRUEif DC ownership changed, FALSE otherwise
*
* History:
*
* 24-Aug-1995 Merge DC ownership routines
*
\**************************************************************************/
BOOL
GreSetDCOwner(
HDC hdc,
W32PID lPid
)
{
BOOL bStatus = FALSE;
PDC_ATTR pDcattr = NULL;
PENTRY pentry;
UINT uiIndex = (UINT) HmgIfromH(hdc);
if (uiIndex < gcMaxHmgr)
{
pentry = &gpentHmgr[uiIndex];
//
// before handle is locked, check if an allocation may
// be needed since DCATTRs can't be allocated under a handle lock.
// Note: instead, we could use a per-process mutex for process list protection.
//
if (lPid == OBJECT_OWNER_CURRENT)
{
pDcattr = HmgAllocateDcAttr();
}
//
// Acquire handle lock. Don't check PID here because owner could be
// NONE, not PUBLIC
//
HANDLELOCK HandleLock(pentry,FALSE);
if (HandleLock.bValid())
{
POBJ pobj = pentry->einfo.pobj;
if ((pentry->Objt == DC_TYPE) && (pentry->FullUnique== HmgUfromH(hdc)))
{
if ((pobj->cExclusiveLock == 0) ||
(pobj->Tid == (PW32THREAD)PsGetCurrentThread()))
{
W32PID lPidBrush = lPid;
//
// Handle is locked. It is illegal to acquire the hmgr resource
// when a handle is locked.
//
#if DBG || defined(PRERELEASE)
//
// check if the rgn selected in the DC is valid
// when USER mark the HDC to be usable again
//
if ((lPid != OBJECT_OWNER_NONE) &&
(HandleLock.Pid() == OBJECT_OWNER_NONE))
{
PDEVOBJ pdo(((PDC)pobj)->hdev());
SURFACE *pSurf = ((PDC)pobj)->pSurface();
REGION *prgn = ((PDC)pobj)->prgnVis();
BOOL bValidateVisrgn = ((PDC)pobj)->bValidateVisrgn();
if (pdo.bValid() && !pdo.bMetaDriver() &&
pSurf && bValidateVisrgn && prgn)
{
BOOL bIsOK = ((pSurf->sizl().cx >= prgn->rcl.right) &&
(pSurf->sizl().cy >= prgn->rcl.bottom)&&
(prgn->rcl.left >= 0) &&
(prgn->rcl.top >= 0));
FREASSERTGDI(bIsOK, "Rgn size is bigger than surface size");
}
}
#endif
if ((lPid == OBJECT_OWNER_NONE) ||
(lPid == OBJECT_OWNER_PUBLIC))
{
//
// free DCATTR if PID matches current process, otherwise
// fail this call. This is an ok path, it just means user has a
// DC on their delayed dc destroy queue and they are trying to
// delete it now from a different process. This doesn't work
// because we have no way of accessing or freeing DC_ATTRs of
// a different process
//
if (HandleLock.Pid() == W32GetCurrentPID())
{
//
// if user mode DC_ATTR is allocated for this dc
//
if (((PDC)pobj)->pDCAttr != &((PDC)pobj)->dcattr)
{
//
// copy pDCAttrs to dcattr, then reset pDCAttr to DC memory
//
((PDC)pobj)->dcattr = *((PDC)pobj)->pDCAttr;
//
// free DCATTR
//
pDcattr = ((PDC)pobj)->pDCAttr;
//
// Set pDCAttr to point to internal structure
//
((PDC)pobj)->pDCAttr = &((PDC)pobj)->dcattr;
//
// clear ENTRY
//
pentry->pUser = NULL;
}
//
// set DC owner to NONE or PUBLIC
//
HandleLock.Pid(lPid);
//
// dec process handle count
//
HmgDecProcessHandleCount(W32GetCurrentPID());
bStatus = TRUE;
}
else if (HandleLock.Pid() == OBJECT_OWNER_NONE)
{
//
// Allow to set from NONE to PUBLIC or NONE.
//
HandleLock.Pid(lPid);
bStatus = TRUE;
}
}
else if (lPid == OBJECT_OWNER_CURRENT)
{
//
// can only set to OBJECT_OWNER_CURRENT if DC is
// not owned, or already owned by current pid.
//
// Get the current PID
//
lPid = W32GetCurrentPID();
if (
(HandleLock.Pid() == lPid) ||
(HandleLock.Pid() == OBJECT_OWNER_NONE) ||
(HandleLock.Pid() == OBJECT_OWNER_PUBLIC)
)
{
BOOL bIncHandleCount = FALSE;
//
// DC may already have DC_ATTR allocated
//
bStatus = TRUE;
//
// only inc handle count if assigning a new PID
//
if (HandleLock.Pid() != lPid)
{
//
// don't check quota for DCs
//
HmgIncProcessHandleCount(lPid,DC_TYPE);
bIncHandleCount = TRUE;
}
//
// check user object not already allocated for this handle
//
if (pentry->pUser == NULL)
{
if (pDcattr != NULL)
{
//
// set DC dc_attr pointer
//
((PDC)pobj)->pDCAttr = pDcattr;
//
// set pUser in ENTRY
//
pentry->pUser = pDcattr;
//
// copy clean attrs
//
*pDcattr = ((PDC)pobj)->dcattr;
//
// set pDcattr to NULL so it is not freed
//
pDcattr = NULL;
}
else
{
WARNING1("HmgSetDCOwnwer failed - No DC_ATTR available\n");
bStatus = FALSE;
//
// Reduce handle quota count
//
if (bIncHandleCount)
{
HmgDecProcessHandleCount(lPid);
}
}
}
if (bStatus)
{
//
// Set new owner
//
HandleLock.Pid(lPid);
}
}
else
{
WARNING("HmgSetDCOwnwer failed, trying to set directly from one PID to another\n");
}
}
else
{
WARNING("HmgSetDCOwnwer failed, bad lPid\n");
}
if((lPidBrush != OBJECT_OWNER_NONE) && bStatus)
{
if(!GreSetBrushOwner((HBRUSH)(((PDC)pobj)->hbrush()),lPidBrush)||
!GreSetBrushOwner((HBRUSH)(((PDC)pobj)->pbrushFill())->hGet(),lPidBrush)||
!GreSetBrushOwner((HBRUSH)(((PDC)pobj)->pbrushLine())->hGet(),lPidBrush))
{
WARNING("HmgSetDCOwner, Brushes could not be moved");
}
}
}
else
{
WARNING1("HmgSetDCOwnwer failed - Handle is exclusively locked\n");
}
}
else
{
WARNING1("HmgSetDCOwnwer failed - bad unique or object type");
}
HandleLock.vUnlock();
}
}
else
{
WARNING1("HmgSetOwner failed - invalid handle index\n");
}
//
// free dcattr if needed
//
if (pDcattr)
{
HmgFreeDcAttr(pDcattr);
}
return(bStatus);
}
/******************************Public*Routine******************************\
* GreSetupDCAttributes
*
* Arguments:
*
* hdc - handle to DC
* pDCAttr - pointer to memory block allocated in USER space by caller
*
* Return Value:
*
* BOOL Status
*
* History:
*
* 24-Apr-1995 -by- Mark Enstrom [marke]
*
\**************************************************************************/
BOOL
GreSetupDCAttributes(
HDC hdc
)
{
BOOL bRet = FALSE;
DCOBJ dco(hdc);
if (dco.bValid())
{
PDC_ATTR pDCAttr = HmgAllocateDcAttr();
if (pDCAttr != NULL)
{
//
// set DC dc_attr pointer
//
dco.pdc->pDCAttr = pDCAttr;
//
// make sure USER object not already allocate for this handle
//
ASSERTGDI(gpentHmgr[HmgIfromH(hdc)].pUser == NULL,
"GreSetupDCAttributes: pUser not NULL");
//
// setup shared global handle table for this DC
//
gpentHmgr[HmgIfromH(hdc)].pUser = pDCAttr;
//
// copy old attrs
//
*pDCAttr = dco.pdc->dcattr;
bRet = TRUE;
}
}
return(bRet);
}
/******************************Public*Routine******************************\
* GreFreeDCAttributes
*
* Arguments:
*
* hdc
*
* Return Value:
*
* BOOL
*
* History:
*
* 27-Apr-1995 -by- Mark Enstrom [marke]
*
\**************************************************************************/
BOOL
GreFreeDCAttributes(
HDC hdc
)
{
BOOL bStatus = FALSE;
DCOBJ dco(hdc);
if (dco.bValid())
{
//
// free dc attribute block if not default, then set to default
//
if (dco.pdc->pDCAttr != &dco.pdc->dcattr)
{
ASSERTGDI(dco.pdc->pDCAttr != NULL,"GreFreeDCAttributes: pDCAttr is NULL");
//
// copy pDCAttrs to dcattr
//
dco.pdc->dcattr = *(dco.pdc->pDCAttr);
//
// free DC_ATTR memory
//
HmgFreeDcAttr(dco.pdc->pDCAttr);
//
// Set pDCAttr to point to internal structure
//
dco.pdc->pDCAttr = &dco.pdc->dcattr;
//
// clear DCATTR in ENTRY
//
gpentHmgr[HmgIfromH(hdc)].pUser = (PDC_ATTR)NULL;
bStatus = TRUE;
}
}
return(bStatus);
}
/****************************************************************************
* NtGdiComputeXformCoefficients
*
* This function is used by the client side char-width caching code. It
* forces computation of the World To Device Transform and puts the
* coefficients in the shared attribute structure. If the world to device
* xform is not just simple scalling it returns FALSE indicating that extents
* and widths should not be cached.
*
*
* History:
* 6/12/1995 by Gerrit van Wingerden [gerritv]
* Wrote it.
*****************************************************************************/
extern "C" BOOL NtGdiComputeXformCoefficients(
HDC hdc // Handle to the DC
)
{
BOOL bRet = FALSE;
XDCOBJ dco(hdc);
if( dco.bValid() )
{
EXFORMOBJ xo(dco, WORLD_TO_DEVICE);
ASSERTGDI(xo.bValid(),"NtGdiFastWidths exformobj not valid\n");
if( xo.bScale() )
{
bRet = TRUE;
}
dco.vUnlockFast();
}
return(bRet);
}
BOOL
bUMPD(
HDC hdc)
{
XDCOBJ dco(hdc);
BOOL bRet = FALSE;
if( dco.bValid())
{
bRet = dco.bUMPD();
dco.vUnlockFast();
}
return(bRet);
}