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.
 
 
 
 
 
 

391 lines
12 KiB

/******************************Module*Header*******************************\
* Module Name: wndobj.hxx
*
* Window object. Created for those drivers that want to track changes
* in the client region.
*
* Created: 27-Sep-1993 15:30:05
* Author: Wendy Wu [wendywu]
*
* Copyright (c) 1993-1999 Microsoft Corporation
\**************************************************************************/
#define WO_NOTIFIED 0x80000000
#define WO_NEW_WNDOBJ 0x40000000
#define WO_SURFACE 0x20000000
#define WO_HSEM_OWNER 0x10000000
#define WO_GENERIC_WNDOBJ 0x08000000
#define WO_NEED_DRAW_NOTIFY 0x04000000
#define WO_SPRITE_OVERLAP 0x02000000 // At least one sprite overlaps
// the window area
#define WO_NOSPRITES 0x01000000 // Don't draw any sprites on
// top of this window
// Internal flag allowed in TRACKOBJ.fl and EWNDOBJ.fl (moved to wglp.h)
#define WO_INTERNAL_VALID_FLAGS (WO_NOTIFIED | \
WO_NEW_WNDOBJ | \
WO_SURFACE | \
WO_HSEM_OWNER | \
WO_NEED_DRAW_NOTIFY | \
WO_SPRITE_OVERLAP | \
WO_NOSPRITES)
#define WO_VALID_FLAGS (WO_RGN_CLIENT_DELTA | \
WO_RGN_CLIENT | \
WO_RGN_SURFACE_DELTA | \
WO_RGN_SURFACE | \
WO_RGN_UPDATE_ALL | \
WO_RGN_WINDOW | \
WO_RGN_DESKTOP_COORD | \
WO_GENERIC_WNDOBJ | \
WO_DRAW_NOTIFY | \
WO_SPRITE_NOTIFY)
// TRACKOBJ and EWNDOBJ identifiers
#define TRACKOBJ_IDENTIFIER 0x43415254 // 'TRAC'
#define EWNDOBJ_IDENTIFIER 0x444E5745 // 'EWND'
// Global that indicates whether to notify driver with the new WNDOBJ
// states following a WNDOBJ creation. User has not changed the window
// states but this is required to initialize the driver. The update is
// done in the parent gdi functions (e.g. SetPixelFormat) that allow
// the DDI to create a WNDOBJ.
extern BOOL gbWndobjUpdate;
// Maximum region rectangle
extern RECTL grclMax;
// Global tracking object (TRACKOBJ) pointer.
// If this is non-null, we are tracking some WNDOBJs in the system.
class TRACKOBJ;
extern TRACKOBJ* gpto;
#if DBG
#define CHECKUSERCRITIN UserAssertUserCritSecIn()
#define CHECKUSERCRITOUT UserAssertUserCritSecOut()
#else
#define CHECKUSERCRITIN
#define CHECKUSERCRITOUT
#endif
// WINBUG #83114 2-7-2000 bhouse Review and test critical section checks
// We are leaving the critical section checks in place eventhough they may
// no longer work if turned on. At some point during code cleanup we should
// review there use and test.
#if DBG
#if 0
#define CHECKCRITIN(hsem) \
ASSERT((ExIsResourceAcquiredExclusiveLite(hsem) == TRUE) || \
(ExIsResourceAcquiredSharedLite(hsem) == TRUE))
#define CHECKCRITOUT(hsem) \
ASSERT(ExIsResourceAcquiredExclusiveLite(hsem) == FALSE)
#else
#define CHECKCRITIN(hsem)
#define CHECKCRITOUT(hsem)
#endif
#define CHECKDEVLOCKIN(dco) \
CHECKCRITIN((dco).hsemDcDevLock)
#define CHECKDEVLOCKOUT(dco) \
CHECKCRITOUT((dco).hsemDcDevLock)
#define CHECKDEVLOCKIN2(pSurface) \
{ \
PDEVOBJ po((pSurface)->hdev()); \
CHECKCRITIN(po.hsemDevLock()); \
}
#define CHECKDEVLOCKOUT2(pSurface) \
{ \
PDEVOBJ po((pSurface)->hdev()); \
CHECKCRITOUT(po.hsemDevLock()); \
}
#else
#define CHECKCRITIN(hsem)
#define CHECKCRITOUT(hsem)
#define CHECKDEVLOCKIN(dco)
#define CHECKDEVLOCKOUT(dco)
#define CHECKDEVLOCKIN2(pSurface)
#define CHECKDEVLOCKOUT2(pSurface)
#endif
/******************************Class***************************************\
* class TRACKOBJ
*
* Each tracking object has a unique driver notification function address
* in the pfn field. There is usually one such object per driver although
* multiple TRACKOBJs can be created on the same device. For example, a
* live video driver may track all live video windows while an OpenGL driver
* tracks all OpenGL windows at the same time. The only restriction is
* that a window can be tracked by only one TRACKOBJ on the same device.
*
* The TRACKOBJ points to a linked list of window objects that is being
* tracked for a given driver notification function.
*
* History:
* 16-Nov-1993 -by- Wendy Wu [wendywu]
* Wrote it.
\**************************************************************************/
class TRACKOBJ
{
public:
ULONG ident;
TRACKOBJ *ptoNext;
EWNDOBJ *pwoSurf;
EWNDOBJ *pwo;
SURFACE *pSurface;
WNDOBJCHANGEPROC pfn;
FLONG fl;
ERECTL erclSurf;
public:
BOOL bValid()
{
return(ident == TRACKOBJ_IDENTIFIER);
}
// Update driver function. fl should not have WOC_RGN_CLIENT_DELTA or
// WOC_RGN_SURFACE_DELTA set.
VOID vUpdateDrv(EWNDOBJ *pwo, FLONG fl)
{
ASSERTGDI(!(fl & (WOC_RGN_CLIENT_DELTA|WOC_RGN_SURFACE_DELTA)),
"TRACKOBJ::vUpdateDrv, Bad flags\n");
(*pfn)((WNDOBJ *)pwo, fl);
}
// Update driver function for delta regions. fl must have
// WOC_RGN_CLIENT_DELTA or WOC_RGN_SURFACE_DELTA set.
// Note that if the delta is empty, we do not need to call the driver.
// The compiler does not allow this function to be inline because of forward
// reference.
VOID vUpdateDrvDelta(EWNDOBJ *pwo, FLONG fl);
};
typedef TRACKOBJ *PTRACKOBJ;
/******************************Class***************************************\
* class EWNDOBJ
*
* A EWNDOBJ is a server side window object created by the driver via
* EngCreateWnd. It is deleted in GreDeletWnd.
*
* Once a WNDOBJ is created, a driver may call WNDOBJ_vSetConsumer to
* set the pvConsumer field to point to its own window data structure.
*
* History:
* 16-Nov-1993 -by- Wendy Wu [wendywu]
* Wrote it.
\**************************************************************************/
class EWNDOBJ : public XCLIPOBJ
{
public:
ULONG ident;
EWNDOBJ *pwoNext;
TRACKOBJ *pto;
HWND hwnd;
FLONG fl;
int ipfd;
// per-WNDOBJ semaphore for generic implementation use only. It is not
// intended for general consumption!
// The surf WNDOBJ does not have a per-WNDOBJ semaphore.
HSEMAPHORE hsem;
public:
BOOL bValid()
{
return(ident == EWNDOBJ_IDENTIFIER && pto->bValid());
}
VOID vSetClip(REGION *prgn, ERECTL erclClient)
{
ASSERTGDI(pto->bValid(), "EWNDOBJ::vSetClip: Invalid pto\n");
// Force it to have a non-trivial complexity.
// Otherwise, it will confuse DDI.
vSetup(prgn, *(ERECTL *) &grclMax, CLIP_NOFORCE);
rclClient = erclClient;
// If the region is empty, set the complexity to DC_RECT.
if (erclExclude().bEmpty())
iDComplexity = DC_RECT;
}
BOOL bDelete()
{
if (fl & WO_HSEM_OWNER)
{
ASSERTGDI(hsem, "EWNDOBJ::bDelete: invalid hsem\n");
GreDeleteSemaphore(hsem);
}
return XCLIPOBJ::bDeleteRGNOBJ(); // delete RGNOBJ
}
VOID vOffset(LONG x, LONG y);
};
typedef EWNDOBJ *PEWNDOBJ;
/******************************Class***************************************\
* class USERCRIT
*
* The USERCRIT object enters the user vis region critical section.
*
* When we are updating the TRACKOBJs and WNDOBJs, we want to be in
* the user critical section to prevent client regions from changing.
*
* Note that the user critical section should not be entered if we hold
* any of the gdi locks (e.g. devlock). This is to prevent deadlock.
*
* History:
* Thu Jan 13 09:55:23 1994 -by- Hock San Lee [hockl]
* Wrote it.
\**************************************************************************/
class USERCRIT
{
private:
BOOL bKeep;
public:
USERCRIT(BOOL bKeepIt = FALSE)
{
CHECKUSERCRITOUT;
UserEnterUserCritSec();
bKeep = bKeepIt;
}
~USERCRIT()
{
if (!bKeep) {
CHECKUSERCRITIN;
UserLeaveUserCritSec();
CHECKUSERCRITOUT;
}
}
};
/******************************Class***************************************\
* class DEVLOCKOBJ_WNDOBJ
*
* This class provides a method to get the current WNDOBJ that is associated
* with a DCOBJ.
*
* History:
* Thu Jan 13 09:55:23 1994 -by- Hock San Lee [hockl]
* Wrote it.
\**************************************************************************/
class DEVLOCKOBJ_WNDOBJ : public DEVLOCKOBJ
{
private:
PEWNDOBJ _pwo;
BOOL bKeepUserCrit;
public:
// Empty constructor
DEVLOCKOBJ_WNDOBJ() {bKeepUserCrit = TRUE;}
// Constructor - Grab the DEVLOCK and lock down the WNDOBJ.
//
// WARNING: This constructor enters the user critical section temporarily
// to get the current WNDOBJ from user. Therefore, the caller
// should not hold the display devlock prior to this constructor.
VOID vConstructor(XDCOBJ& dco)
{
// Assume no WNDOBJ.
_pwo = (PEWNDOBJ)NULL;
// Make sure that we don't have devlock before entering user critical
// section. Otherwise, it can cause deadlock.
if (dco.bDisplay() && dco.dctp() == DCTYPE_DIRECT)
{
CHECKDEVLOCKOUT(dco);
}
// Enter user critical section.
USERCRIT usercrit(bKeepUserCrit);
// Grab the devlock.
DEVLOCKOBJ::bLock(dco);
// If it is a display DC, get the pwo that the hdc is associated with.
// If it is a printer or memory DC, get the pwo from pSurface.
if (dco.bDisplay() && dco.dctp() == DCTYPE_DIRECT)
{
HWND hwnd;
if (!UserGetHwnd(dco.hdc(), &hwnd, (PVOID *) &_pwo, FALSE))
{
SAVE_ERROR_CODE(ERROR_INVALID_HANDLE);
}
}
else
{
_pwo = dco.pwo();
}
}
DEVLOCKOBJ_WNDOBJ(XDCOBJ& dco, BOOL bKeep = TRUE)
{
bKeepUserCrit = bKeep;
vConstructor(dco);
}
// Destructor - Free the DEVLOCK.
~DEVLOCKOBJ_WNDOBJ()
{
// We need to release devlock then user crit in that order
DEVLOCKOBJ::vDestructorNULL();
if (bKeepUserCrit) {
CHECKUSERCRITIN;
UserLeaveUserCritSec();
CHECKUSERCRITOUT;
}
}
// bValidWndobj - Do we have a WNDOBJ for this DC?
BOOL bValidWndobj() { return(_pwo != (PEWNDOBJ)NULL); }
// bValidDevlock - Is the devlock valid?
BOOL bValidDevlock() { return(DEVLOCKOBJ::bValid()); }
// pwo - Get the WNDOBJ pointer for this DC
PEWNDOBJ pwo() { return(_pwo); }
// vInit - Initialize the stack object
VOID vInit()
{
_pwo = (PEWNDOBJ) NULL;
DEVLOCKOBJ::vInit();
}
};
VOID vForceClientRgnUpdate();
VOID vChangeWndObjs(SURFACE*, HDEV, SURFACE*, HDEV);
VOID vTransferWndObjs(SURFACE*, HDEV, HDEV);