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

  1. /******************************Module*Header*******************************\
  2. * Module Name: wndobj.hxx
  3. *
  4. * Window object. Created for those drivers that want to track changes
  5. * in the client region.
  6. *
  7. * Created: 27-Sep-1993 15:30:05
  8. * Author: Wendy Wu [wendywu]
  9. *
  10. * Copyright (c) 1993-1999 Microsoft Corporation
  11. \**************************************************************************/
  12. #define WO_NOTIFIED 0x80000000
  13. #define WO_NEW_WNDOBJ 0x40000000
  14. #define WO_SURFACE 0x20000000
  15. #define WO_HSEM_OWNER 0x10000000
  16. #define WO_GENERIC_WNDOBJ 0x08000000
  17. #define WO_NEED_DRAW_NOTIFY 0x04000000
  18. #define WO_SPRITE_OVERLAP 0x02000000 // At least one sprite overlaps
  19. // the window area
  20. #define WO_NOSPRITES 0x01000000 // Don't draw any sprites on
  21. // top of this window
  22. // Internal flag allowed in TRACKOBJ.fl and EWNDOBJ.fl (moved to wglp.h)
  23. #define WO_INTERNAL_VALID_FLAGS (WO_NOTIFIED | \
  24. WO_NEW_WNDOBJ | \
  25. WO_SURFACE | \
  26. WO_HSEM_OWNER | \
  27. WO_NEED_DRAW_NOTIFY | \
  28. WO_SPRITE_OVERLAP | \
  29. WO_NOSPRITES)
  30. #define WO_VALID_FLAGS (WO_RGN_CLIENT_DELTA | \
  31. WO_RGN_CLIENT | \
  32. WO_RGN_SURFACE_DELTA | \
  33. WO_RGN_SURFACE | \
  34. WO_RGN_UPDATE_ALL | \
  35. WO_RGN_WINDOW | \
  36. WO_RGN_DESKTOP_COORD | \
  37. WO_GENERIC_WNDOBJ | \
  38. WO_DRAW_NOTIFY | \
  39. WO_SPRITE_NOTIFY)
  40. // TRACKOBJ and EWNDOBJ identifiers
  41. #define TRACKOBJ_IDENTIFIER 0x43415254 // 'TRAC'
  42. #define EWNDOBJ_IDENTIFIER 0x444E5745 // 'EWND'
  43. // Global that indicates whether to notify driver with the new WNDOBJ
  44. // states following a WNDOBJ creation. User has not changed the window
  45. // states but this is required to initialize the driver. The update is
  46. // done in the parent gdi functions (e.g. SetPixelFormat) that allow
  47. // the DDI to create a WNDOBJ.
  48. extern BOOL gbWndobjUpdate;
  49. // Maximum region rectangle
  50. extern RECTL grclMax;
  51. // Global tracking object (TRACKOBJ) pointer.
  52. // If this is non-null, we are tracking some WNDOBJs in the system.
  53. class TRACKOBJ;
  54. extern TRACKOBJ* gpto;
  55. #if DBG
  56. #define CHECKUSERCRITIN UserAssertUserCritSecIn()
  57. #define CHECKUSERCRITOUT UserAssertUserCritSecOut()
  58. #else
  59. #define CHECKUSERCRITIN
  60. #define CHECKUSERCRITOUT
  61. #endif
  62. // WINBUG #83114 2-7-2000 bhouse Review and test critical section checks
  63. // We are leaving the critical section checks in place eventhough they may
  64. // no longer work if turned on. At some point during code cleanup we should
  65. // review there use and test.
  66. #if DBG
  67. #if 0
  68. #define CHECKCRITIN(hsem) \
  69. ASSERT((ExIsResourceAcquiredExclusiveLite(hsem) == TRUE) || \
  70. (ExIsResourceAcquiredSharedLite(hsem) == TRUE))
  71. #define CHECKCRITOUT(hsem) \
  72. ASSERT(ExIsResourceAcquiredExclusiveLite(hsem) == FALSE)
  73. #else
  74. #define CHECKCRITIN(hsem)
  75. #define CHECKCRITOUT(hsem)
  76. #endif
  77. #define CHECKDEVLOCKIN(dco) \
  78. CHECKCRITIN((dco).hsemDcDevLock)
  79. #define CHECKDEVLOCKOUT(dco) \
  80. CHECKCRITOUT((dco).hsemDcDevLock)
  81. #define CHECKDEVLOCKIN2(pSurface) \
  82. { \
  83. PDEVOBJ po((pSurface)->hdev()); \
  84. CHECKCRITIN(po.hsemDevLock()); \
  85. }
  86. #define CHECKDEVLOCKOUT2(pSurface) \
  87. { \
  88. PDEVOBJ po((pSurface)->hdev()); \
  89. CHECKCRITOUT(po.hsemDevLock()); \
  90. }
  91. #else
  92. #define CHECKCRITIN(hsem)
  93. #define CHECKCRITOUT(hsem)
  94. #define CHECKDEVLOCKIN(dco)
  95. #define CHECKDEVLOCKOUT(dco)
  96. #define CHECKDEVLOCKIN2(pSurface)
  97. #define CHECKDEVLOCKOUT2(pSurface)
  98. #endif
  99. /******************************Class***************************************\
  100. * class TRACKOBJ
  101. *
  102. * Each tracking object has a unique driver notification function address
  103. * in the pfn field. There is usually one such object per driver although
  104. * multiple TRACKOBJs can be created on the same device. For example, a
  105. * live video driver may track all live video windows while an OpenGL driver
  106. * tracks all OpenGL windows at the same time. The only restriction is
  107. * that a window can be tracked by only one TRACKOBJ on the same device.
  108. *
  109. * The TRACKOBJ points to a linked list of window objects that is being
  110. * tracked for a given driver notification function.
  111. *
  112. * History:
  113. * 16-Nov-1993 -by- Wendy Wu [wendywu]
  114. * Wrote it.
  115. \**************************************************************************/
  116. class TRACKOBJ
  117. {
  118. public:
  119. ULONG ident;
  120. TRACKOBJ *ptoNext;
  121. EWNDOBJ *pwoSurf;
  122. EWNDOBJ *pwo;
  123. SURFACE *pSurface;
  124. WNDOBJCHANGEPROC pfn;
  125. FLONG fl;
  126. ERECTL erclSurf;
  127. public:
  128. BOOL bValid()
  129. {
  130. return(ident == TRACKOBJ_IDENTIFIER);
  131. }
  132. // Update driver function. fl should not have WOC_RGN_CLIENT_DELTA or
  133. // WOC_RGN_SURFACE_DELTA set.
  134. VOID vUpdateDrv(EWNDOBJ *pwo, FLONG fl)
  135. {
  136. ASSERTGDI(!(fl & (WOC_RGN_CLIENT_DELTA|WOC_RGN_SURFACE_DELTA)),
  137. "TRACKOBJ::vUpdateDrv, Bad flags\n");
  138. (*pfn)((WNDOBJ *)pwo, fl);
  139. }
  140. // Update driver function for delta regions. fl must have
  141. // WOC_RGN_CLIENT_DELTA or WOC_RGN_SURFACE_DELTA set.
  142. // Note that if the delta is empty, we do not need to call the driver.
  143. // The compiler does not allow this function to be inline because of forward
  144. // reference.
  145. VOID vUpdateDrvDelta(EWNDOBJ *pwo, FLONG fl);
  146. };
  147. typedef TRACKOBJ *PTRACKOBJ;
  148. /******************************Class***************************************\
  149. * class EWNDOBJ
  150. *
  151. * A EWNDOBJ is a server side window object created by the driver via
  152. * EngCreateWnd. It is deleted in GreDeletWnd.
  153. *
  154. * Once a WNDOBJ is created, a driver may call WNDOBJ_vSetConsumer to
  155. * set the pvConsumer field to point to its own window data structure.
  156. *
  157. * History:
  158. * 16-Nov-1993 -by- Wendy Wu [wendywu]
  159. * Wrote it.
  160. \**************************************************************************/
  161. class EWNDOBJ : public XCLIPOBJ
  162. {
  163. public:
  164. ULONG ident;
  165. EWNDOBJ *pwoNext;
  166. TRACKOBJ *pto;
  167. HWND hwnd;
  168. FLONG fl;
  169. int ipfd;
  170. // per-WNDOBJ semaphore for generic implementation use only. It is not
  171. // intended for general consumption!
  172. // The surf WNDOBJ does not have a per-WNDOBJ semaphore.
  173. HSEMAPHORE hsem;
  174. public:
  175. BOOL bValid()
  176. {
  177. return(ident == EWNDOBJ_IDENTIFIER && pto->bValid());
  178. }
  179. VOID vSetClip(REGION *prgn, ERECTL erclClient)
  180. {
  181. ASSERTGDI(pto->bValid(), "EWNDOBJ::vSetClip: Invalid pto\n");
  182. // Force it to have a non-trivial complexity.
  183. // Otherwise, it will confuse DDI.
  184. vSetup(prgn, *(ERECTL *) &grclMax, CLIP_NOFORCE);
  185. rclClient = erclClient;
  186. // If the region is empty, set the complexity to DC_RECT.
  187. if (erclExclude().bEmpty())
  188. iDComplexity = DC_RECT;
  189. }
  190. BOOL bDelete()
  191. {
  192. if (fl & WO_HSEM_OWNER)
  193. {
  194. ASSERTGDI(hsem, "EWNDOBJ::bDelete: invalid hsem\n");
  195. GreDeleteSemaphore(hsem);
  196. }
  197. return XCLIPOBJ::bDeleteRGNOBJ(); // delete RGNOBJ
  198. }
  199. VOID vOffset(LONG x, LONG y);
  200. };
  201. typedef EWNDOBJ *PEWNDOBJ;
  202. /******************************Class***************************************\
  203. * class USERCRIT
  204. *
  205. * The USERCRIT object enters the user vis region critical section.
  206. *
  207. * When we are updating the TRACKOBJs and WNDOBJs, we want to be in
  208. * the user critical section to prevent client regions from changing.
  209. *
  210. * Note that the user critical section should not be entered if we hold
  211. * any of the gdi locks (e.g. devlock). This is to prevent deadlock.
  212. *
  213. * History:
  214. * Thu Jan 13 09:55:23 1994 -by- Hock San Lee [hockl]
  215. * Wrote it.
  216. \**************************************************************************/
  217. class USERCRIT
  218. {
  219. private:
  220. BOOL bKeep;
  221. public:
  222. USERCRIT(BOOL bKeepIt = FALSE)
  223. {
  224. CHECKUSERCRITOUT;
  225. UserEnterUserCritSec();
  226. bKeep = bKeepIt;
  227. }
  228. ~USERCRIT()
  229. {
  230. if (!bKeep) {
  231. CHECKUSERCRITIN;
  232. UserLeaveUserCritSec();
  233. CHECKUSERCRITOUT;
  234. }
  235. }
  236. };
  237. /******************************Class***************************************\
  238. * class DEVLOCKOBJ_WNDOBJ
  239. *
  240. * This class provides a method to get the current WNDOBJ that is associated
  241. * with a DCOBJ.
  242. *
  243. * History:
  244. * Thu Jan 13 09:55:23 1994 -by- Hock San Lee [hockl]
  245. * Wrote it.
  246. \**************************************************************************/
  247. class DEVLOCKOBJ_WNDOBJ : public DEVLOCKOBJ
  248. {
  249. private:
  250. PEWNDOBJ _pwo;
  251. BOOL bKeepUserCrit;
  252. public:
  253. // Empty constructor
  254. DEVLOCKOBJ_WNDOBJ() {bKeepUserCrit = TRUE;}
  255. // Constructor - Grab the DEVLOCK and lock down the WNDOBJ.
  256. //
  257. // WARNING: This constructor enters the user critical section temporarily
  258. // to get the current WNDOBJ from user. Therefore, the caller
  259. // should not hold the display devlock prior to this constructor.
  260. VOID vConstructor(XDCOBJ& dco)
  261. {
  262. // Assume no WNDOBJ.
  263. _pwo = (PEWNDOBJ)NULL;
  264. // Make sure that we don't have devlock before entering user critical
  265. // section. Otherwise, it can cause deadlock.
  266. if (dco.bDisplay() && dco.dctp() == DCTYPE_DIRECT)
  267. {
  268. CHECKDEVLOCKOUT(dco);
  269. }
  270. // Enter user critical section.
  271. USERCRIT usercrit(bKeepUserCrit);
  272. // Grab the devlock.
  273. DEVLOCKOBJ::bLock(dco);
  274. // If it is a display DC, get the pwo that the hdc is associated with.
  275. // If it is a printer or memory DC, get the pwo from pSurface.
  276. if (dco.bDisplay() && dco.dctp() == DCTYPE_DIRECT)
  277. {
  278. HWND hwnd;
  279. if (!UserGetHwnd(dco.hdc(), &hwnd, (PVOID *) &_pwo, FALSE))
  280. {
  281. SAVE_ERROR_CODE(ERROR_INVALID_HANDLE);
  282. }
  283. }
  284. else
  285. {
  286. _pwo = dco.pwo();
  287. }
  288. }
  289. DEVLOCKOBJ_WNDOBJ(XDCOBJ& dco, BOOL bKeep = TRUE)
  290. {
  291. bKeepUserCrit = bKeep;
  292. vConstructor(dco);
  293. }
  294. // Destructor - Free the DEVLOCK.
  295. ~DEVLOCKOBJ_WNDOBJ()
  296. {
  297. // We need to release devlock then user crit in that order
  298. DEVLOCKOBJ::vDestructorNULL();
  299. if (bKeepUserCrit) {
  300. CHECKUSERCRITIN;
  301. UserLeaveUserCritSec();
  302. CHECKUSERCRITOUT;
  303. }
  304. }
  305. // bValidWndobj - Do we have a WNDOBJ for this DC?
  306. BOOL bValidWndobj() { return(_pwo != (PEWNDOBJ)NULL); }
  307. // bValidDevlock - Is the devlock valid?
  308. BOOL bValidDevlock() { return(DEVLOCKOBJ::bValid()); }
  309. // pwo - Get the WNDOBJ pointer for this DC
  310. PEWNDOBJ pwo() { return(_pwo); }
  311. // vInit - Initialize the stack object
  312. VOID vInit()
  313. {
  314. _pwo = (PEWNDOBJ) NULL;
  315. DEVLOCKOBJ::vInit();
  316. }
  317. };
  318. VOID vForceClientRgnUpdate();
  319. VOID vChangeWndObjs(SURFACE*, HDEV, SURFACE*, HDEV);
  320. VOID vTransferWndObjs(SURFACE*, HDEV, HDEV);