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