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