ReactOS  0.4.15-dev-2087-g6bfb76b
gdiobj.c
Go to the documentation of this file.
1 /*
2  * PROJECT: ReactOS win32 kernel mode subsystem
3  * LICENSE: GPL - See COPYING in the top level directory
4  * FILE: win32ss/gdi/ntgdi/gdiobj.c
5  * PURPOSE: General GDI object manipulation routines
6  * PROGRAMMERS: Timo Kreuzer
7  */
8 
9 /*
10  * If you want to understand this code, you need to start thinking in portals.
11  * - gpaulRefCount is a global pointer to an allocated array of ULONG values,
12  * one for each handle. Bits 0 - 22 contain a reference count for the handle.
13  * It gets increased for each handle lock / reference. Bit 23 contains a valid
14  * bit. If this bit is 0, the handle got deleted and will be pushed to the free
15  * list, once all references are gone. Bits 24 - 31 contain the reuse value of
16  * the handle, which allows to check if the entry was changed before atomically
17  * exchanging the reference count.
18  * - Objects can exist with or without a handle
19  * - Objects with a handle can be locked either exclusively or shared.
20  * Both locks increase the handle reference count in gpaulRefCount.
21  * Exclusive locks also increase the BASEOBJECT's cExclusiveLock field
22  * and the first lock (can be acquired recursively) acquires a pushlock
23  * that is also stored in the BASEOBJECT.
24  * - Objects without a handle cannot have exclusive locks. Their reference
25  * count is tracked in the BASEOBJECT's ulShareCount field.
26  * - An object that is inserted in the handle table automatically has an
27  * exclusive lock. For objects that are "shared objects" (BRUSH, PALETTE, ...)
28  * this is the only way it can ever be exclusively locked. It prevents the
29  * object from being locked by another thread. A shared lock will simply fail,
30  * while an exclusive lock will succeed after the object was unlocked.
31  *
32  * Ownership:
33  *
34  * Owner: POWNED PUBLIC NONE spec
35  * ---------------------------------------------------
36  * LockForRead + + - PUBLIC
37  * LockForWrite + - - POWNED
38  * LockAny + + + NONE
39  * NtGdiDeleteObjectApp + - - PUBLIC
40  * GreDeleteObject + + + NONE
41  * GreSetOwner(POWNED) - - + -
42  * GreSetOwner(PUBLIC) + - + -
43  * GreSetOwner(NONE) + - - -
44  *
45  */
46 
47 /* INCLUDES ******************************************************************/
48 
49 #include <win32k.h>
50 #define NDEBUG
51 #include <debug.h>
52 
54 ULONG
57 {
58  return *Source;
59 }
60 
62 void
64  _In_ HANDLE hobj)
65 {
68  if (pti)
69  {
70 #if DBG
71  pti->acExclusiveLockCount[((ULONG_PTR)hobj >> 16) & 0x1f]++;
72 #endif
73  pti->cExclusiveLocks++;
74  }
75 }
76 
78 void
80  _In_ HANDLE hobj)
81 {
84  if (pti)
85  {
86 #if DBG
87  pti->acExclusiveLockCount[((ULONG_PTR)hobj >> 16) & 0x1f]--;
88 #endif
89  pti->cExclusiveLocks--;
90  }
91 }
92 
93 #if DBG
94 VOID
96  _In_ UCHAR objt)
97 {
99  ULONG i;
100 
101  if (pti)
102  {
103  /* Ensure correct locking order! */
104  for (i = objt + 1; i < GDIObjTypeTotal; i++)
105  {
106  NT_ASSERT(pti->acExclusiveLockCount[i] == 0);
107  }
108  }
109 }
110 #define ASSERT_SHARED_OBJECT_TYPE(objt) \
111  ASSERT((objt) == GDIObjType_SURF_TYPE || \
112  (objt) == GDIObjType_PAL_TYPE || \
113  (objt) == GDIObjType_LFONT_TYPE || \
114  (objt) == GDIObjType_PATH_TYPE || \
115  (objt) == GDIObjType_BRUSH_TYPE)
116 #define ASSERT_EXCLUSIVE_OBJECT_TYPE(objt) \
117  ASSERT((objt) == GDIObjType_DC_TYPE || \
118  (objt) == GDIObjType_RGN_TYPE || \
119  (objt) == GDIObjType_UMPD_TYPE || \
120  (objt) == GDIObjType_META_TYPE)
121 #define ASSERT_TRYLOCK_OBJECT_TYPE(objt) \
122  ASSERT((objt) == GDIObjType_DRVOBJ_TYPE)
123 #else
124 #define ASSERT_LOCK_ORDER(hobj)
125 #define ASSERT_SHARED_OBJECT_TYPE(objt)
126 #define ASSERT_EXCLUSIVE_OBJECT_TYPE(objt)
127 #define ASSERT_TRYLOCK_OBJECT_TYPE(objt)
128 #endif
129 
130 #if defined(_M_IX86) || defined(_M_AMD64)
131 #define InterlockedOr16 _InterlockedOr16
132 #endif
133 
134 #define GDIOBJ_POOL_TAG(type) ('00hG' + (((type) & 0x1f) << 24))
135 
136 enum
137 {
138  REF_MASK_REUSE = 0xff000000,
139  REF_INC_REUSE = 0x01000000,
140  REF_MASK_VALID = 0x00800000,
141  REF_MASK_COUNT = 0x007fffff,
142  REF_MASK_INUSE = 0x00ffffff,
143 };
144 
145 /* GLOBALS *******************************************************************/
146 
147 /* Per session handle table globals */
154 
155 static VOID NTAPI GDIOBJ_vCleanup(PVOID ObjectBody);
156 
157 static const
160 {
161  NULL, /* 00 GDIObjType_DEF_TYPE */
162  DC_vCleanup, /* 01 GDIObjType_DC_TYPE */
163  NULL, /* 02 GDIObjType_UNUSED1_TYPE */
164  NULL, /* 03 GDIObjType_UNUSED2_TYPE */
165  REGION_vCleanup, /* 04 GDIObjType_RGN_TYPE */
166  SURFACE_vCleanup, /* 05 GDIObjType_SURF_TYPE */
167  GDIOBJ_vCleanup, /* 06 GDIObjType_CLIENTOBJ_TYPE */
168  GDIOBJ_vCleanup, /* 07 GDIObjType_PATH_TYPE */
169  PALETTE_vCleanup, /* 08 GDIObjType_PAL_TYPE */
170  GDIOBJ_vCleanup, /* 09 GDIObjType_ICMLCS_TYPE */
171  GDIOBJ_vCleanup, /* 0a GDIObjType_LFONT_TYPE */
172  NULL, /* 0b GDIObjType_RFONT_TYPE, unused */
173  NULL, /* 0c GDIObjType_PFE_TYPE, unused */
174  NULL, /* 0d GDIObjType_PFT_TYPE, unused */
175  GDIOBJ_vCleanup, /* 0e GDIObjType_ICMCXF_TYPE */
176  NULL, /* 0f GDIObjType_SPRITE_TYPE, unused */
177  NULL, /* 10 GDIObjType_BRUSH_TYPE, BRUSH, PEN, EXTPEN */
178  NULL, /* 11 GDIObjType_UMPD_TYPE, unused */
179  NULL, /* 12 GDIObjType_UNUSED4_TYPE */
180  NULL, /* 13 GDIObjType_SPACE_TYPE, unused */
181  NULL, /* 14 GDIObjType_UNUSED5_TYPE */
182  GDIOBJ_vCleanup, /* 15 GDIObjType_META_TYPE */
183  NULL, /* 16 GDIObjType_EFSTATE_TYPE, unused */
184  NULL, /* 17 GDIObjType_BMFD_TYPE, unused */
185  NULL, /* 18 GDIObjType_VTFD_TYPE, unused */
186  NULL, /* 19 GDIObjType_TTFD_TYPE, unused */
187  NULL, /* 1a GDIObjType_RC_TYPE, unused */
188  NULL, /* 1b GDIObjType_TEMP_TYPE, unused */
189  DRIVEROBJ_vCleanup,/* 1c GDIObjType_DRVOBJ_TYPE */
190  NULL, /* 1d GDIObjType_DCIOBJ_TYPE, unused */
191  NULL, /* 1e GDIObjType_SPOOL_TYPE, unused */
192  NULL, /* 1f reserved entry */
193 };
194 
195 static const
198 {
199  NULL, /* 00 GDIObjType_DEF_TYPE */
200  NULL, /* 01 GDIObjType_DC_TYPE */
201  NULL, /* 02 GDIObjType_UNUSED1_TYPE */
202  NULL, /* 03 GDIObjType_UNUSED2_TYPE */
203  NULL, /* 04 GDIObjType_RGN_TYPE */
204  NULL, /* 05 GDIObjType_SURF_TYPE */
205  NULL, /* 06 GDIObjType_CLIENTOBJ_TYPE */
206  NULL, /* 07 GDIObjType_PATH_TYPE */
207  NULL, /* 08 GDIObjType_PAL_TYPE */
208  NULL, /* 09 GDIObjType_ICMLCS_TYPE */
209  NULL, /* 0a GDIObjType_LFONT_TYPE */
210  NULL, /* 0b GDIObjType_RFONT_TYPE, unused */
211  NULL, /* 0c GDIObjType_PFE_TYPE, unused */
212  NULL, /* 0d GDIObjType_PFT_TYPE, unused */
213  NULL, /* 0e GDIObjType_ICMCXF_TYPE */
214  NULL, /* 0f GDIObjType_SPRITE_TYPE, unused */
215  BRUSH_vDeleteObject, /* 10 GDIObjType_BRUSH_TYPE, BRUSH, PEN, EXTPEN */
216  NULL, /* 11 GDIObjType_UMPD_TYPE, unused */
217  NULL, /* 12 GDIObjType_UNUSED4_TYPE */
218  NULL, /* 13 GDIObjType_SPACE_TYPE, unused */
219  NULL, /* 14 GDIObjType_UNUSED5_TYPE */
220  NULL, /* 15 GDIObjType_META_TYPE, unused */
221  NULL, /* 16 GDIObjType_EFSTATE_TYPE, unused */
222  NULL, /* 17 GDIObjType_BMFD_TYPE, unused */
223  NULL, /* 18 GDIObjType_VTFD_TYPE, unused */
224  NULL, /* 19 GDIObjType_TTFD_TYPE, unused */
225  NULL, /* 1a GDIObjType_RC_TYPE, unused */
226  NULL, /* 1b GDIObjType_TEMP_TYPE, unused */
227  NULL, /* 1c GDIObjType_DRVOBJ_TYPE */
228  NULL, /* 1d GDIObjType_DCIOBJ_TYPE, unused */
229  NULL, /* 1e GDIObjType_SPOOL_TYPE, unused */
230  NULL, /* 1f reserved entry */
231 };
232 
233 /* INTERNAL FUNCTIONS ********************************************************/
234 
235 static
236 VOID
237 NTAPI
239 {
240  /* Nothing to do */
241 }
242 
243 static
244 VOID
246 {
248  NULL,
249  NULL,
250  0,
251  cjSize,
252  GDITAG_HMGR_LOOKASIDE_START + (objt << 24),
253  0);
254 }
255 
256 CODE_SEG("INIT")
257 NTSTATUS
258 NTAPI
260 {
262  LARGE_INTEGER liSize;
263  PVOID pvSection;
264  SIZE_T cjViewSize = 0;
265 
266  /* Create a section for the shared handle table */
267  liSize.QuadPart = sizeof(GDI_HANDLE_TABLE); // GDI_HANDLE_COUNT * sizeof(ENTRY);
270  NULL,
271  &liSize,
273  SEC_COMMIT | 0x1,
274  NULL,
275  NULL);
276  if (!NT_SUCCESS(status))
277  {
278  DPRINT1("INITGDI: Could not allocate a GDI handle table.\n");
279  return status;
280  }
281 
282  /* Map the section in session space */
284  (PVOID*)&gpentHmgr,
285  &cjViewSize);
286  if (!NT_SUCCESS(status))
287  {
288  DPRINT1("INITGDI: Failed to map handle table section\n");
290  return status;
291  }
292 
293  /* Allocate memory for the reference counter table */
294  gpaulRefCount = EngAllocSectionMem(&pvSection,
296  GDI_HANDLE_COUNT * sizeof(ULONG),
297  'frHG');
298  if (!gpaulRefCount)
299  {
300  DPRINT1("INITGDI: Failed to allocate reference table.\n");
303  }
304 
305  gulFirstFree = 0;
307 
309 
310  /* Initialize the lookaside lists */
314  if(!gpaLookasideList)
315  return STATUS_NO_MEMORY;
316 
326 
327  return STATUS_SUCCESS;
328 }
329 
331 VOID
333 {
335  if (ppi) InterlockedIncrement((LONG*)&ppi->GDIHandleCount);
336 }
337 
339 VOID
341 {
343  if (ppi) InterlockedDecrement((LONG*)&ppi->GDIHandleCount);
344 }
345 
346 static inline
347 VOID
349 {
350  PEPROCESS pep;
351  PPROCESSINFO ppi;
353 
354  Status = PsLookupProcessByProcessId(ULongToHandle(ulProcessId), &pep);
357 
358  ppi = PsGetProcessWin32Process(pep);
359  if (ppi) InterlockedIncrement((LONG*)&ppi->GDIHandleCount);
361 }
362 
363 static inline
364 VOID
366 {
367  PEPROCESS pep;
368  PPROCESSINFO ppi;
370 
371  Status = PsLookupProcessByProcessId(ULongToHandle(ulProcessId), &pep);
374 
375  ppi = PsGetProcessWin32Process(pep);
376  if (ppi) InterlockedDecrement((LONG*)&ppi->GDIHandleCount);
378 }
379 
380 static
381 PENTRY
383 {
384  ULONG iFirst, iNext, iPrev;
385  PENTRY pentFree;
386 
387  DPRINT("Enter InterLockedPopFreeEntry\n");
388 
389  do
390  {
391  /* Get the index and sequence number of the first free entry */
393 
394  /* Check if we have a free entry */
395  if (!(iFirst & GDI_HANDLE_INDEX_MASK))
396  {
397  /* Increment FirstUnused and get the new index */
398  iFirst = InterlockedIncrement((LONG*)&gulFirstUnused) - 1;
399 
400  /* Check if we have unused entries left */
401  if (iFirst >= GDI_HANDLE_COUNT)
402  {
403  DPRINT1("No more GDI handles left!\n");
404 #if DBG_ENABLE_GDIOBJ_BACKTRACES
405  DbgDumpGdiHandleTableWithBT();
406 #endif
408  return 0;
409  }
410 
411  /* Return the old entry */
412  return &gpentHmgr[iFirst];
413  }
414 
415  /* Get a pointer to the first free entry */
416  pentFree = &gpentHmgr[iFirst & GDI_HANDLE_INDEX_MASK];
417 
418  /* Create a new value with an increased sequence number */
419  iNext = GDI_HANDLE_GET_INDEX(pentFree->einfo.hFree);
420  iNext |= (iFirst & ~GDI_HANDLE_INDEX_MASK) + 0x10000;
421 
422  /* Try to exchange the FirstFree value */
424  iNext,
425  iFirst);
426  }
427  while (iPrev != iFirst);
428 
429  /* Sanity check: is entry really free? */
430  ASSERT(((ULONG_PTR)pentFree->einfo.pobj & ~GDI_HANDLE_INDEX_MASK) == 0);
431 
432  return pentFree;
433 }
434 
435 /* Pushes an entry of the handle table to the free list,
436  The entry must not have any references left */
437 static
438 VOID
440 {
441  ULONG iToFree, iFirst, iPrev, idxToFree;
442 
443  DPRINT("Enter ENTRY_vPushFreeEntry\n");
444 
445  idxToFree = pentFree - gpentHmgr;
446  ASSERT((gpaulRefCount[idxToFree] & REF_MASK_INUSE) == 0);
447 
448  /* Initialize entry */
449  pentFree->Objt = GDIObjType_DEF_TYPE;
450  pentFree->ObjectOwner.ulObj = 0;
451  pentFree->pUser = NULL;
452 
453  /* Increase reuse counter in entry and reference counter */
455  pentFree->FullUnique += 0x0100;
456 
457  do
458  {
459  /* Get the current first free index and sequence number */
461 
462  /* Set the einfo.pobj member to the index of the first free entry */
463  pentFree->einfo.pobj = UlongToPtr(iFirst & GDI_HANDLE_INDEX_MASK);
464 
465  /* Combine new index and increased sequence number in iToFree */
466  iToFree = idxToFree | ((iFirst & ~GDI_HANDLE_INDEX_MASK) + 0x10000);
467 
468  /* Try to atomically update the first free entry */
470  iToFree,
471  iFirst);
472  }
473  while (iPrev != iFirst);
474 }
475 
476 static
477 PENTRY
479 {
480  ULONG ulIndex, cNewRefs, cOldRefs;
481  PENTRY pentry;
482 
483  /* Get the handle index and check if its too big */
485 
486  /* Get pointer to the entry */
487  pentry = &gpentHmgr[ulIndex];
488 
489  /* Get the current reference count */
490  cOldRefs = gpaulRefCount[ulIndex];
491 
492  do
493  {
494  /* Check if the slot is deleted */
495  if ((cOldRefs & REF_MASK_VALID) == 0)
496  {
497  DPRINT("GDIOBJ: Slot is not valid: 0x%lx, hobh=%p\n", cOldRefs, hobj);
498  return NULL;
499  }
500 
501  /* Check if the unique value matches */
502  if (pentry->FullUnique != (USHORT)((ULONG_PTR)hobj >> 16))
503  {
504  DPRINT("GDIOBJ: Wrong unique value. Handle: 0x%4x, entry: 0x%4x\n",
505  (USHORT)((ULONG_PTR)hobj >> 16), pentry->FullUnique);
506  return NULL;
507  }
508 
509  /* Check if the object owner is this process or public */
510  if (!(fl & GDIOBJFLAG_IGNOREPID) &&
513  {
514  DPRINT("GDIOBJ: Cannot reference foreign handle %p, pentry=%p:%lx.\n",
515  hobj, pentry, pentry->ObjectOwner.ulObj);
516  return NULL;
517  }
518 
519  /* Try to atomically increment the reference count */
520  cNewRefs = cOldRefs + 1;
522  cNewRefs,
523  cOldRefs);
524  }
525  while (cNewRefs != cOldRefs + 1);
526 
527  /* Integrity checks */
528  ASSERT((pentry->FullUnique & 0x1f) == pentry->Objt);
529  ASSERT(pentry->einfo.pobj != NULL);
530 
531  /* Check if lower 32 bits match, the upper 32 bits are ignored */
532  ASSERT(pentry->einfo.pobj->hHmgr == UlongToPtr(PtrToUlong(hobj)));
533 
534  return pentry;
535 }
536 
537 static
538 HGDIOBJ
539 ENTRY_hInsertObject(PENTRY pentry, POBJ pobj, UCHAR objt, ULONG ulOwner)
540 {
541  ULONG ulIndex;
542 
543  /* Calculate the handle index */
544  ulIndex = pentry - gpentHmgr;
545 
546  /* Update the fields in the ENTRY */
547  pentry->einfo.pobj = pobj;
548  pentry->Objt = objt & 0x1f;
549  pentry->FullUnique = (pentry->FullUnique & 0xff00) | objt;
550  pentry->ObjectOwner.ulObj = ulOwner;
551 
552  /* Make the handle valid with 1 reference */
555 
556  /* Return the handle */
557  return (HGDIOBJ)(((ULONG_PTR)pentry->FullUnique << 16) | ulIndex);
558 }
559 
560 POBJ
561 NTAPI
563 {
564  POBJ pobj;
565 
566  if (fl & BASEFLAG_LOOKASIDE)
567  {
568  /* Allocate the object from a lookaside list */
569  pobj = ExAllocateFromPagedLookasideList(&gpaLookasideList[objt & 0x1f]);
570  }
571  else
572  {
573  /* Allocate the object from paged pool */
575  }
576 
577  if (!pobj) return NULL;
578 
579  /* Initialize the object */
580  RtlZeroMemory(pobj, cjSize);
581  pobj->hHmgr = (HGDIOBJ)((ULONG_PTR)objt << 16);
582  pobj->cExclusiveLock = 0;
583  pobj->ulShareCount = 1;
584  pobj->BaseFlags = fl & 0xffff;
585  DBG_INITLOG(&pobj->slhLog);
586  DBG_LOGEVENT(&pobj->slhLog, EVENT_ALLOCATE, 0);
587 #if DBG_ENABLE_GDIOBJ_BACKTRACES
588  DbgCaptureStackBackTace(pobj->apvBackTrace, 1, GDI_OBJECT_STACK_LEVELS);
589 #endif /* GDI_DEBUG */
590 
591  return pobj;
592 }
593 
594 VOID
595 NTAPI
597 {
598  UCHAR objt;
599 
600  DBG_CLEANUP_EVENT_LIST(&pobj->slhLog);
601 
602  /* Get the object type */
603  objt = ((ULONG_PTR)pobj->hHmgr >> 16) & 0x1f;
604 
605  /* Check if we have a delete procedure (for C++ based objects) */
606  if (apfnDelete[objt] != NULL)
607  {
608  /* Invoke the delete procedure */
609  apfnDelete[objt](pobj);
610  }
611  else
612  {
613  /* Call the cleanup procedure */
614  NT_ASSERT(apfnCleanup[objt]);
615  apfnCleanup[objt](pobj);
616 
617  /* Check if the object is allocated from a lookaside list */
618  if (pobj->BaseFlags & BASEFLAG_LOOKASIDE)
619  {
620  ExFreeToPagedLookasideList(&gpaLookasideList[objt], pobj);
621  }
622  else
623  {
624  ExFreePoolWithTag(pobj, GDIOBJ_POOL_TAG(objt));
625  }
626  }
627 }
628 
629 VOID
630 NTAPI
632 {
633  ULONG cRefs, ulIndex;
634 
635  /* Calculate the index */
637 
638  /* Check if the object has a handle */
639  if (ulIndex)
640  {
641  /* Decrement reference count */
642  if ((gpaulRefCount[ulIndex] & REF_MASK_COUNT) == 0)
643  {
644  DBG_DUMP_EVENT_LIST(&pobj->slhLog);
645  }
648  DBG_LOGEVENT(&pobj->slhLog, EVENT_DEREFERENCE, cRefs);
649 
650  /* Check if we reached 0 and handle bit is not set */
651  if ((cRefs & REF_MASK_INUSE) == 0)
652  {
653  /* Make sure it's ok to delete the object */
655 
656  /* Check if the handle was process owned */
657  if (gpentHmgr[ulIndex].ObjectOwner.ulObj != GDI_OBJ_HMGR_PUBLIC &&
659  {
660  /* Decrement the process handle count */
661  ASSERT(gpentHmgr[ulIndex].ObjectOwner.ulObj ==
664  }
665 
666  /* Push entry to the free list */
668 
669  /* Free the object */
670  GDIOBJ_vFreeObject(pobj);
671  }
672  }
673  else
674  {
675  /* Decrement the objects reference count */
676  ASSERT(pobj->ulShareCount > 0);
677  cRefs = InterlockedDecrement((LONG*)&pobj->ulShareCount);
678  DBG_LOGEVENT(&pobj->slhLog, EVENT_DEREFERENCE, cRefs);
679 
680  /* Check if we reached 0 */
681  if (cRefs == 0)
682  {
683  /* Free the object */
684  GDIOBJ_vFreeObject(pobj);
685  }
686  }
687 }
688 
689 POBJ
690 NTAPI
692  HGDIOBJ hobj,
693  UCHAR objt)
694 {
695  PENTRY pentry;
696  POBJ pobj;
697 
698  /* Check if the handle type matches */
700  if ((((ULONG_PTR)hobj >> 16) & 0x1f) != objt)
701  {
702  DPRINT("GDIOBJ: Wrong type. handle=%p, type=%x\n", hobj, objt);
703  return NULL;
704  }
705 
706  /* Reference the handle entry */
707  pentry = ENTRY_ReferenceEntryByHandle(hobj, 0);
708  if (!pentry)
709  {
710  DPRINT("GDIOBJ: Requested handle 0x%p is not valid.\n", hobj);
711  return NULL;
712  }
713 
714  /* Get the pointer to the BASEOBJECT */
715  pobj = pentry->einfo.pobj;
716 
717  /* Check if the object is exclusively locked */
718  if (pobj->cExclusiveLock != 0)
719  {
720  DPRINT1("GDIOBJ: Cannot reference object %p with exclusive lock.\n", hobj);
722  DBG_DUMP_EVENT_LIST(&pobj->slhLog);
723  return NULL;
724  }
725 
726  DBG_LOGEVENT(&pobj->slhLog, EVENT_REFERENCE, gpaulRefCount[pentry - gpentHmgr]);
727 
728  /* All is well, return the object */
729  return pobj;
730 }
731 
732 VOID
733 NTAPI
735 {
736  ULONG cRefs;
737 
738  /* Check if the object has a handle */
739  if (GDI_HANDLE_GET_INDEX(pobj->hHmgr))
740  {
741  /* Increase the handle's reference count */
745  }
746  else
747  {
748  /* Increase the object's reference count */
749  cRefs = InterlockedIncrement((LONG*)&pobj->ulShareCount);
750  }
751 
752  DBG_LOGEVENT(&pobj->slhLog, EVENT_REFERENCE, cRefs);
753 }
754 
755 PGDIOBJ
756 NTAPI
758  HGDIOBJ hobj,
759  UCHAR objt)
760 {
761  PENTRY pentry;
762  POBJ pobj;
764 
765  /* Check if the handle type matches */
767  if ((((ULONG_PTR)hobj >> 16) & 0x1f) != objt)
768  {
769  DPRINT("Wrong object type: hobj=0x%p, objt=0x%x\n", hobj, objt);
770  return NULL;
771  }
772 
773  /* Make sure lock order is correct */
774  ASSERT_LOCK_ORDER(objt);
775 
776  /* Reference the handle entry */
777  pentry = ENTRY_ReferenceEntryByHandle(hobj, 0);
778  if (!pentry)
779  {
780  DPRINT("GDIOBJ: Requested handle 0x%p is not valid.\n", hobj);
781  return NULL;
782  }
783 
784  /* Get the pointer to the BASEOBJECT */
785  pobj = pentry->einfo.pobj;
786 
787  /* Check if we already own the lock */
789  if (pobj->dwThreadId != dwThreadId)
790  {
791  /* Disable APCs and try acquiring the push lock */
794  {
795  ULONG cRefs, ulIndex;
796  /* Already owned. Clean up and leave. */
798 
799  /* Calculate the index */
801 
802  /* Decrement reference count */
805  ASSERT(cRefs & REF_MASK_VALID);
806 
807  return NULL;
808  }
809 
810  /* Set us as lock owner */
811  ASSERT(pobj->dwThreadId == 0);
812  pobj->dwThreadId = dwThreadId;
813  }
814 
815  /* Increase lock count */
816  pobj->cExclusiveLock++;
818  DBG_LOGEVENT(&pobj->slhLog, EVENT_LOCK, 0);
819 
820  /* Return the object */
821  return pobj;
822 }
823 
824 PGDIOBJ
825 NTAPI
827  HGDIOBJ hobj,
828  UCHAR objt)
829 {
830  PENTRY pentry;
831  POBJ pobj;
833 
834  /* Check if the handle type matches */
836  if ((((ULONG_PTR)hobj >> 16) & 0x1f) != objt)
837  {
838  DPRINT("Wrong object type: hobj=0x%p, objt=0x%x\n", hobj, objt);
839  return NULL;
840  }
841 
842  /* Make sure lock order is correct */
843  ASSERT_LOCK_ORDER(objt);
844 
845  /* Reference the handle entry */
846  pentry = ENTRY_ReferenceEntryByHandle(hobj, 0);
847  if (!pentry)
848  {
849  DPRINT("GDIOBJ: Requested handle 0x%p is not valid.\n", hobj);
850  return NULL;
851  }
852 
853  /* Get the pointer to the BASEOBJECT */
854  pobj = pentry->einfo.pobj;
855 
856  /* Check if we already own the lock */
858  if (pobj->dwThreadId != dwThreadId)
859  {
860  /* Disable APCs and acquire the push lock */
863 
864  /* Set us as lock owner */
865  ASSERT(pobj->dwThreadId == 0);
866  pobj->dwThreadId = dwThreadId;
867  }
868 
869  /* Increase lock count */
870  pobj->cExclusiveLock++;
872  DBG_LOGEVENT(&pobj->slhLog, EVENT_LOCK, 0);
873 
874  /* Return the object */
875  return pobj;
876 }
877 
878 VOID
879 NTAPI
881 {
882  ULONG cRefs, ulIndex;
883  ASSERT(pobj->cExclusiveLock > 0);
884 
885  /* Decrease lock count */
886  pobj->cExclusiveLock--;
888  DBG_LOGEVENT(&pobj->slhLog, EVENT_UNLOCK, 0);
889 
890  /* Check if this was the last lock */
891  if (pobj->cExclusiveLock == 0)
892  {
893  /* Reset lock owner */
894  pobj->dwThreadId = 0;
895 
896  /* Release the pushlock and reenable APCs */
899  }
900 
901  /* Calculate the index */
903 
904  /* Decrement reference count */
907  ASSERT(cRefs & REF_MASK_VALID);
908 }
909 
910 HGDIOBJ
911 NTAPI
913  POBJ pobj,
914  ULONG ulOwner)
915 {
916  PENTRY pentry;
917  UCHAR objt;
918 
919  /* Must have no handle and only one reference */
920  ASSERT(GDI_HANDLE_GET_INDEX(pobj->hHmgr) == 0);
921  ASSERT(pobj->cExclusiveLock == 0);
922  ASSERT(pobj->ulShareCount == 1);
923 
924  /* Get a free handle entry */
925  pentry = ENTRY_pentPopFreeEntry();
926  if (!pentry)
927  {
928  DPRINT1("GDIOBJ: Could not get a free entry.\n");
929  return NULL;
930  }
931 
932  /* Make the object exclusively locked */
936  pobj->cExclusiveLock = 1;
939 
940  /* Get object type from the hHmgr field */
941  objt = ((ULONG_PTR)pobj->hHmgr >> 16) & 0xff;
942  ASSERT(objt != GDIObjType_DEF_TYPE);
943 
944  /* Check if current process is requested owner */
945  if (ulOwner == GDI_OBJ_HMGR_POWNED)
946  {
947  /* Increment the process handle count */
949 
950  /* Use Process id */
952  }
953 
954  /* Insert the object into the handle table */
955  pobj->hHmgr = ENTRY_hInsertObject(pentry, pobj, objt, ulOwner);
956 
957  /* Return the handle */
958  DPRINT("GDIOBJ: Created handle: %p\n", pobj->hHmgr);
959  DBG_LOGEVENT(&pobj->slhLog, EVENT_CREATE_HANDLE, 0);
960  return pobj->hHmgr;
961 }
962 
963 VOID
964 NTAPI
966  POBJ pobj,
967  ULONG ulNewOwner)
968 {
969  PENTRY pentry;
970  ULONG ulOldOwner;
971 
972  /* This is a ugly HACK, needed to fix IntGdiSetDCOwnerEx */
973  if (GDI_HANDLE_IS_STOCKOBJ(pobj->hHmgr))
974  {
975  DPRINT("Trying to set ownership of stock object %p to %lx\n", pobj->hHmgr, ulNewOwner);
976  return;
977  }
978 
979  /* Get the handle entry */
981  pentry = &gpentHmgr[GDI_HANDLE_GET_INDEX(pobj->hHmgr)];
982 
983  /* Check if the new owner is the same as the old one */
984  ulOldOwner = pentry->ObjectOwner.ulObj;
985  if (ulOldOwner == ulNewOwner)
986  {
987  /* Nothing to do */
988  return;
989  }
990 
991  /* Is the current process requested? */
992  if (ulNewOwner == GDI_OBJ_HMGR_POWNED)
993  {
994  /* Use process id */
995  ulNewOwner = HandleToUlong(PsGetCurrentProcessId());
996  }
997 
998  // HACK
999  if (ulNewOwner == GDI_OBJ_HMGR_NONE)
1000  ulNewOwner = GDI_OBJ_HMGR_PUBLIC;
1001 
1002  /* Was the object process owned? */
1003  if ((ulOldOwner != GDI_OBJ_HMGR_PUBLIC) &&
1004  (ulOldOwner != GDI_OBJ_HMGR_NONE))
1005  {
1006  /* Decrement the previous owners handle count */
1007  DecrementGdiHandleCount(ulOldOwner);
1008  }
1009 
1010  /* Is the new owner a process? */
1011  if ((ulNewOwner != GDI_OBJ_HMGR_PUBLIC) &&
1012  (ulNewOwner != GDI_OBJ_HMGR_NONE))
1013  {
1014  /* Increment the new owners handle count */
1015  IncrementGdiHandleCount(ulNewOwner);
1016  }
1017  else
1018  {
1019  /* Make sure we don't leak user mode memory */
1020  NT_ASSERT(pentry->pUser == NULL);
1021  }
1022 
1023  /* Set new owner */
1024  pentry->ObjectOwner.ulObj = ulNewOwner;
1025  DBG_LOGEVENT(&pobj->slhLog, EVENT_SET_OWNER, 0);
1026 }
1027 
1028 /* Locks 2 or 3 objects at a time */
1029 BOOL
1030 NTAPI
1032  IN ULONG ulCount,
1033  IN HGDIOBJ* ahObj,
1034  OUT PGDIOBJ* apObj,
1035  IN UCHAR objt)
1036 {
1037  UINT auiIndices[3] = {0, 1, 2};
1038  UINT i, j, tmp;
1039 
1040  ASSERT(ulCount <= 3);
1041 
1042  /* Sort the handles */
1043  for (i = 0; i < ulCount - 1; i++)
1044  {
1045  for (j = i + 1; j < ulCount; j++)
1046  {
1047  if ((ULONG_PTR)ahObj[auiIndices[i]] <
1048  (ULONG_PTR)ahObj[auiIndices[j]])
1049  {
1050  tmp = auiIndices[i];
1051  auiIndices[i] = auiIndices[j];
1052  auiIndices[j] = tmp;
1053  }
1054  }
1055  }
1056 
1057  /* Lock the objects in safe order */
1058  for (i = 0; i < ulCount; i++)
1059  {
1060  /* Skip NULL handles */
1061  if (ahObj[auiIndices[i]] == NULL)
1062  {
1063  apObj[auiIndices[i]] = NULL;
1064  continue;
1065  }
1066 
1067  /* Lock the object */
1068  apObj[auiIndices[i]] = GDIOBJ_LockObject(ahObj[auiIndices[i]], objt);
1069 
1070  /* Check for failure */
1071  if (apObj[auiIndices[i]] == NULL)
1072  {
1073  /* Cleanup */
1074  while (i--)
1075  {
1076  if (apObj[auiIndices[i]])
1077  GDIOBJ_vUnlockObject(apObj[auiIndices[i]]);
1078  }
1079  return FALSE;
1080  }
1081  }
1082 
1083  return TRUE;
1084 }
1085 
1086 PVOID
1087 NTAPI
1089 {
1091  return gpentHmgr[ulIndex].pUser;
1092 }
1093 
1094 VOID
1095 NTAPI
1097 {
1098  ULONG ulIndex;
1099 
1100  ASSERT(pobj->hHmgr);
1101 
1102  /* Get the handle index */
1104 
1105  /* Set pointer to the usermode attribute */
1106  gpentHmgr[ulIndex].pUser = pvObjAttr;
1107 }
1108 
1109 VOID
1110 NTAPI
1112 {
1113  ULONG ulIndex;
1114 
1115  /* Set the object's delete flag */
1117  DBG_LOGEVENT(&pobj->slhLog, EVENT_DELETE, 0);
1118 
1119  /* Get the handle index */
1121  if (ulIndex)
1122  {
1123  /* Reset the handle valid bit */
1125 
1126  /* Check if the object is exclusively locked */
1127  if (pobj->cExclusiveLock != 0)
1128  {
1129  /* Reset lock owner and lock count */
1130  pobj->dwThreadId = 0;
1131  pobj->cExclusiveLock = 0;
1132 
1133  /* Release the pushlock and reenable APCs */
1137  }
1138  }
1139 
1140  /* Dereference the object (will take care of deletion) */
1142 }
1143 
1144 BOOL
1145 NTAPI
1147 {
1148  PENTRY pentry;
1149 
1150  pentry = ENTRY_ReferenceEntryByHandle(hobj, 0);
1151  if (!pentry) return FALSE;
1153  return TRUE;
1154 }
1155 
1156 BOOL
1157 NTAPI
1159 {
1160  PENTRY pentry;
1161 
1162  /* Check for stock objects */
1163  if (GDI_HANDLE_IS_STOCKOBJ(hobj))
1164  {
1165  DPRINT1("GreDeleteObject: Cannot delete stock object %p.\n", hobj);
1166  return FALSE;
1167  }
1168 
1169  /* Reference the handle entry */
1170  pentry = ENTRY_ReferenceEntryByHandle(hobj, 0);
1171  if (!pentry)
1172  {
1173  DPRINT1("GreDeleteObject: Trying to delete invalid object %p\n", hobj);
1174  return FALSE;
1175  }
1176 
1177  /* Check for public owner */
1178  if (pentry->ObjectOwner.ulObj == GDI_OBJ_HMGR_PUBLIC)
1179  {
1180  DPRINT1("GreDeleteObject: Trying to delete global object %p\n", hobj);
1182  return FALSE;
1183  }
1184 
1185  /* Delete the object */
1186  GDIOBJ_vDeleteObject(pentry->einfo.pobj);
1187  return TRUE;
1188 }
1189 
1190 ULONG
1191 NTAPI
1193 {
1194  ULONG ulIndex, ulOwner;
1195 
1196  /* Get the handle index */
1197  ulIndex = GDI_HANDLE_GET_INDEX(hobj);
1198 
1199  /* Check if the handle is valid */
1200  if (ulIndex >= GDI_HANDLE_COUNT ||
1202  ((ULONG_PTR)hobj >> 16) != gpentHmgr[ulIndex].FullUnique)
1203  {
1204  DPRINT1("GreGetObjectOwner: invalid handle 0x%p.\n", hobj);
1205  return GDI_OBJ_HMGR_RESTRICTED;
1206  }
1207 
1208  /* Get the object owner */
1209  ulOwner = gpentHmgr[ulIndex].ObjectOwner.ulObj;
1210 
1211  if (ulOwner == HandleToUlong(PsGetCurrentProcessId()))
1212  return GDI_OBJ_HMGR_POWNED;
1213 
1214  if (ulOwner == GDI_OBJ_HMGR_PUBLIC)
1215  return GDI_OBJ_HMGR_PUBLIC;
1216 
1217  return GDI_OBJ_HMGR_RESTRICTED;
1218 }
1219 
1220 BOOL
1221 NTAPI
1223  HGDIOBJ hobj,
1224  ULONG ulOwner,
1225  ULONG Flags)
1226 {
1227  PENTRY pentry;
1228 
1229  /* Check for stock objects */
1230  if (GDI_HANDLE_IS_STOCKOBJ(hobj))
1231  {
1232  DPRINT("GreSetObjectOwner: Got stock object %p\n", hobj);
1233  return FALSE;
1234  }
1235 
1236  /* Reference the handle entry */
1237  pentry = ENTRY_ReferenceEntryByHandle(hobj, Flags);
1238  if (!pentry)
1239  {
1240  DPRINT("GreSetObjectOwner: Invalid handle 0x%p.\n", hobj);
1241  return FALSE;
1242  }
1243 
1244  /* Call internal function */
1245  GDIOBJ_vSetObjectOwner(pentry->einfo.pobj, ulOwner);
1246 
1247  /* Dereference the object */
1249 
1250  return TRUE;
1251 }
1252 
1253 BOOL
1254 NTAPI
1256  HGDIOBJ hobj,
1257  ULONG ulOwner)
1258 {
1259  return GreSetObjectOwnerEx(hobj, ulOwner, 0);
1260 }
1261 
1262 INT
1263 NTAPI
1265  IN HGDIOBJ hobj,
1266  IN INT cbCount,
1267  OUT PVOID pvBuffer)
1268 {
1269  PVOID pvObj;
1270  UCHAR objt;
1271  INT iResult = 0;
1272 
1273  /* Verify object type */
1274  objt = ((ULONG_PTR)hobj >> 16) & 0x1f;
1275  if (objt != GDIObjType_BRUSH_TYPE &&
1276  objt != GDIObjType_SURF_TYPE &&
1277  objt != GDIObjType_LFONT_TYPE &&
1278  objt != GDIObjType_PAL_TYPE)
1279  {
1280  DPRINT1("GreGetObject: Invalid object type\n");
1281  return 0;
1282  }
1283 
1284  pvObj = GDIOBJ_ReferenceObjectByHandle(hobj, objt);
1285  if (!pvObj)
1286  {
1287  DPRINT("GreGetObject: Could not lock object\n");
1288  return 0;
1289  }
1290 
1291  switch (GDI_HANDLE_GET_TYPE(hobj))
1292  {
1295  iResult = PEN_GetObject(pvObj, cbCount, pvBuffer);
1296  break;
1297 
1299  iResult = BRUSH_GetObject(pvObj, cbCount, pvBuffer);
1300  break;
1301 
1303  iResult = BITMAP_GetObject(pvObj, cbCount, pvBuffer);
1304  break;
1305 
1307  iResult = FontGetObject(pvObj, cbCount, pvBuffer);
1308  break;
1309 
1311  iResult = PALETTE_GetObject(pvObj, cbCount, pvBuffer);
1312  break;
1313 
1314  default:
1315  DPRINT1("GDI object type of 0x%p not implemented\n", hobj);
1316  break;
1317  }
1318 
1320  return iResult;
1321 }
1322 
1323 W32KAPI
1324 INT
1325 APIENTRY
1327  IN HANDLE hobj,
1328  IN INT cjBufferSize,
1330 {
1331  UINT iResult, cjMaxSize;
1332  union
1333  {
1334  BITMAP bitmap;
1335  DIBSECTION dibsection;
1336  LOGPEN logpen;
1337  LOGBRUSH logbrush;
1338  LOGFONTW logfontw;
1339  EXTLOGFONTW extlogfontw;
1340  ENUMLOGFONTEXDVW enumlogfontexdvw;
1341  } object;
1342 
1343  /* Normalize to the largest supported object size */
1344  cjMaxSize = min((UINT)cjBufferSize, sizeof(object));
1345 
1346  /* Now do the actual call */
1347  iResult = GreGetObject(hobj, cjMaxSize, lpBuffer ? &object : NULL);
1348 
1349  /* Check if we have a buffer and data */
1350  if ((lpBuffer != NULL) && (iResult != 0))
1351  {
1352  /* Enter SEH for buffer transfer */
1353  _SEH2_TRY
1354  {
1355  /* Probe the buffer and copy it */
1356  cjMaxSize = min(cjMaxSize, iResult);
1357  ProbeForWrite(lpBuffer, cjMaxSize, sizeof(WORD));
1358  RtlCopyMemory(lpBuffer, &object, cjMaxSize);
1359  }
1361  {
1362  /* Clear the return value.
1363  * Do *NOT* set last error here! */
1364  iResult = 0;
1365  }
1366  _SEH2_END;
1367  }
1368 
1369  /* Return the count */
1370  return iResult;
1371 }
1372 
1373 W32KAPI
1374 HANDLE
1375 APIENTRY
1377  IN ULONG ulType)
1378 {
1379  POBJ pObject;
1380  HANDLE handle;
1381 
1382  /* Check if ulType is valid */
1386  {
1387  DPRINT1("NtGdiCreateClientObj: Invalid object type 0x%lx.\n", ulType);
1388  return NULL;
1389  }
1390 
1391  /* Allocate a new object */
1393  sizeof(CLIENTOBJ),
1395  if (!pObject)
1396  {
1397  DPRINT1("NtGdiCreateClientObj: Could not allocate a clientobj.\n");
1398  return NULL;
1399  }
1400 
1401  /* Set the real object type */
1403 
1404  /* Create a handle */
1406  if (!handle)
1407  {
1408  DPRINT1("NtGdiCreateClientObj: Could not create a handle.\n");
1410  return NULL;
1411  }
1412 
1413  /* Unlock it */
1415 
1416  return handle;
1417 }
1418 
1419 W32KAPI
1420 BOOL
1421 APIENTRY
1423  IN HANDLE hobj)
1424 {
1425  /* We first need to get the real type from the handle */
1427 
1428  /* Check if it's really a CLIENTOBJ */
1430  {
1431  /* FIXME: SetLastError? */
1432  return FALSE;
1433  }
1434 
1435  return GreDeleteObject(hobj);
1436 }
1437 
1438 
1439 
1441 
1442 PGDIOBJ NTAPI
1443 GDIOBJ_ShareLockObj(HGDIOBJ hObj, DWORD ExpectedType)
1444 {
1445  if (ExpectedType == GDI_OBJECT_TYPE_DONTCARE)
1446  ExpectedType = GDI_HANDLE_GET_TYPE(hObj);
1447  return GDIOBJ_ReferenceObjectByHandle(hObj, (ExpectedType >> 16) & 0x1f);
1448 }
1449 
1450 // This function is not safe to use with concurrent deleting attempts
1451 // That shouldn't be a problem, since we don't have any processes yet,
1452 // that could delete the handle
1453 BOOL
1454 NTAPI
1456 {
1457  PENTRY pentry;
1458  POBJ pobj;
1459 
1460  /* Reference the handle entry */
1461  pentry = ENTRY_ReferenceEntryByHandle(*phObj, 0);
1462  if (!pentry)
1463  {
1464  DPRINT1("GDIOBJ: Requested handle 0x%p is not valid.\n", *phObj);
1465  return FALSE;
1466  }
1467 
1468  /* Update the entry */
1469  pentry->FullUnique |= GDI_ENTRY_STOCK_MASK;
1470  pentry->ObjectOwner.ulObj = 0;
1471 
1472  /* Get the pointer to the BASEOBJECT */
1473  pobj = pentry->einfo.pobj;
1474 
1475  /* Calculate the new handle */
1476  pobj->hHmgr = (HGDIOBJ)((ULONG_PTR)pobj->hHmgr | GDI_HANDLE_STOCK_MASK);
1477 
1478  /* Return the new handle */
1479  *phObj = pobj->hHmgr;
1480 
1481  /* Dereference the handle */
1483 
1484  return TRUE;
1485 }
1486 
1487 POBJ NTAPI
1489 {
1490  POBJ pobj;
1491  FLONG fl = 0;
1492  UCHAR objt = (ObjectType >> 16) & 0xFF;
1493 
1494  if ((objt == GDIObjType_DC_TYPE && cjSize == sizeof(DC)) ||
1495  (objt == GDIObjType_PAL_TYPE && cjSize == sizeof(PALETTE)) ||
1496  (objt == GDIObjType_RGN_TYPE && cjSize == sizeof(REGION)) ||
1497  (objt == GDIObjType_SURF_TYPE && cjSize == sizeof(SURFACE)) ||
1498  (objt == GDIObjType_PATH_TYPE && cjSize == sizeof(PATH)))
1499  {
1501  }
1502 
1503  pobj = GDIOBJ_AllocateObject(objt, cjSize, fl);
1504  if (!pobj)
1505  {
1506  return NULL;
1507  }
1508 
1510  {
1511  GDIOBJ_vFreeObject(pobj);
1512  return NULL;
1513  }
1514  return pobj;
1515 }
1516 
1517 PVOID NTAPI
1519 {
1520  PVOID pvMappedView = NULL;
1521  NTSTATUS Status;
1522  LARGE_INTEGER liOffset;
1523  SIZE_T cjViewSize = sizeof(GDI_HANDLE_TABLE);
1524 
1525  liOffset.QuadPart = 0;
1526 
1528  ASSERT(pProcess != NULL);
1529 
1531  pProcess,
1532  &pvMappedView,
1533  0,
1534  0,
1535  &liOffset,
1536  &cjViewSize,
1537  ViewUnmap,
1538  SEC_NO_CHANGE,
1539  PAGE_READONLY);
1540 
1541  if (!NT_SUCCESS(Status))
1542  return NULL;
1543 
1544  return pvMappedView;
1545 }
1546 
1547 BOOL NTAPI
1549 {
1550  PENTRY pentry;
1551  ULONG ulIndex;
1552  DWORD dwProcessId;
1553  PPROCESSINFO ppi;
1554 
1555  DPRINT("CleanupForProcess prochandle %p Pid %p\n",
1556  Process, Process->UniqueProcessId);
1557 
1559 
1560  /* Get the current process Id */
1561  dwProcessId = PtrToUlong(PsGetCurrentProcessId());
1562 
1563  /* Loop all handles in the handle table */
1565  {
1566  pentry = &gpentHmgr[ulIndex];
1567 
1568  /* Check if the object is owned by the process */
1569  if (pentry->ObjectOwner.ulObj == dwProcessId)
1570  {
1571  ASSERT(pentry->einfo.pobj->cExclusiveLock == 0);
1572 
1573  /* Reference the object and delete it */
1575  GDIOBJ_vDeleteObject(pentry->einfo.pobj);
1576  }
1577  }
1578 
1579 #if DBG
1581 #endif
1582 
1584  DPRINT("Completed cleanup for process %p\n", Process->UniqueProcessId);
1585  if (ppi->GDIHandleCount != 0)
1586  {
1587  DPRINT1("Leaking %d handles!\n", ppi->GDIHandleCount);
1588  ASSERT(FALSE);
1589  }
1590 
1591  /* Loop all handles in the handle table */
1593  {
1594  pentry = &gpentHmgr[ulIndex];
1595 
1596  /* Check if the object is owned by the process */
1597  if (pentry->ObjectOwner.ulObj == dwProcessId)
1598  {
1599  DPRINT1("Leaking object. Index=%lx, type=0x%x, refcount=%lx\n",
1600  ulIndex, pentry->Objt, gpaulRefCount[ulIndex]);
1601  DBG_DUMP_EVENT_LIST(&pentry->einfo.pobj->slhLog);
1602  //DBG_CLEANUP_EVENT_LIST(&pentry->einfo.pobj->slhLog);
1603  ASSERT(FALSE);
1604  }
1605  }
1606 
1607  return TRUE;
1608 }
1609 
1611 PGDI_POOL
1613 {
1614  PPROCESSINFO ppi;
1615 
1617  NT_ASSERT(ppi != NULL);
1618 
1619  return ppi->pPoolBrushAttr;
1620 }
1621 
1622 /* EOF */
ULONG NTAPI DbgCaptureStackBackTace(_Out_writes_(cFramesToCapture) PVOID *ppvFrames, _In_ ULONG cFramesToSkip, _In_ ULONG cFramesToCapture)
#define GDI_HANDLE_GET_INDEX(h)
Definition: gdi.h:28
ObjectType
Definition: metafile.c:80
FORCEINLINE VOID ExAcquirePushLockExclusive(PEX_PUSH_LOCK PushLock)
Definition: ex.h:1010
FxObject * pObject
#define IN
Definition: typedefs.h:39
PGDIOBJ NTAPI GDIOBJ_LockObject(HGDIOBJ hobj, UCHAR objt)
Definition: gdiobj.c:826
VOID(NTAPI * GDIOBJDELETEPROC)(PVOID ObjectBody)
Definition: gdiobj.h:34
#define ULongToHandle(h)
Definition: basetsd.h:81
BOOL NTAPI GreSetObjectOwner(HGDIOBJ hobj, ULONG ulOwner)
Definition: gdiobj.c:1255
#define InterlockedAnd
Definition: interlocked.h:62
BOOL NTAPI GreDeleteObject(HGDIOBJ hobj)
Definition: gdiobj.c:1158
struct _GDI_POOL * pPoolBrushAttr
Definition: win32.h:284
VOID NTAPI ExInitializePagedLookasideList(IN PPAGED_LOOKASIDE_LIST Lookaside, IN PALLOCATE_FUNCTION Allocate OPTIONAL, IN PFREE_FUNCTION Free OPTIONAL, IN ULONG Flags, IN SIZE_T Size, IN ULONG Tag, IN USHORT Depth)
Definition: lookas.c:270
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
PVOID pUser
Definition: ntgdihdl.h:251
struct _PALETTE PALETTE
BOOL NTAPI GreIsHandleValid(HGDIOBJ hobj)
Definition: gdiobj.c:1146
ULONG ulShareCount
Definition: gdiobj.h:42
volatile ULONG gulFirstUnused
Definition: gdiobj.c:152
#define GDI_OBJ_HMGR_RESTRICTED
Definition: ntgdihdl.h:119
POBJ NTAPI GDIOBJ_ReferenceObjectByHandle(HGDIOBJ hobj, UCHAR objt)
Definition: gdiobj.c:691
coclass MSXML2::XSLTemplate40 object
static int cbCount
Definition: fiber.c:42
#define _Interlocked_operand_
Definition: no_sal2.h:410
#define GDITAG_HMGR_LOOKASIDE_START
Definition: tags.h:130
#define TRUE
Definition: types.h:120
INT APIENTRY BITMAP_GetObject(SURFACE *psurf, INT Count, LPVOID buffer)
Definition: bitmaps.c:766
#define DBG_INITLOG(pslh)
Definition: gdidebug.h:110
#define DBG_UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:318
UCHAR Objt
Definition: ntgdihdl.h:249
static PPAGED_LOOKASIDE_LIST gpaLookasideList
Definition: gdiobj.c:153
PVOID NTAPI GDI_MapHandleTable(PEPROCESS pProcess)
Definition: gdiobj.c:1518
PVOID NTAPI PsGetProcessWin32Process(PEPROCESS Process)
Definition: process.c:1193
_In_ CLIPOBJ _In_ BRUSHOBJ _In_ LONG x1
Definition: winddi.h:3706
PVOID NTAPI PsGetCurrentThreadWin32Thread(VOID)
Definition: thread.c:805
static VOID DecrementGdiHandleCount(ULONG ulProcessId)
Definition: gdiobj.c:365
LONG NTSTATUS
Definition: precomp.h:26
#define ASSERT_TRYLOCK_OBJECT_TYPE(objt)
Definition: gdiobj.c:127
#define HandleToUlong(h)
Definition: basetsd.h:79
Definition: path.h:34
#define GDI_HANDLE_INDEX_MASK
Definition: gdi.h:16
static VOID InitLookasideList(UCHAR objt, ULONG cjSize)
Definition: gdiobj.c:245
#define InterlockedCompareExchange
Definition: interlocked.h:104
struct _BASEOBJECT * pobj
Definition: ntgdihdl.h:234
DWORD dwThreadId
Definition: gdiobj.h:43
INT FASTCALL BRUSH_GetObject(PBRUSH pbr, INT cjBuffer, LPLOGBRUSH plbBuffer)
Definition: brush.cpp:260
VOID NTAPI GDIOBJ_vDereferenceObject(POBJ pobj)
Definition: gdiobj.c:631
#define GDI_ENTRY_STOCK_MASK
Definition: ntgdihdl.h:33
USHORT cExclusiveLock
Definition: gdiobj.h:45
ULONG NTAPI GreGetObjectOwner(HGDIOBJ hobj)
Definition: gdiobj.c:1192
volatile ULONG gulFirstFree
Definition: gdiobj.c:151
HGDIOBJ hHmgr
Definition: gdiobj.h:40
int32_t INT
Definition: typedefs.h:58
VOID NTAPI ProbeForWrite(IN PVOID Address, IN SIZE_T Length, IN ULONG Alignment)
Definition: exintrin.c:143
FORCEINLINE VOID DecrementCurrentProcessGdiHandleCount(void)
Definition: gdiobj.c:340
#define GDI_HANDLE_BASETYPE_MASK
Definition: gdi.h:18
INT FASTCALL PALETTE_GetObject(PPALETTE ppal, INT cbCount, LPLOGBRUSH lpBuffer)
Definition: palette.c:247
USHORT BaseFlags
Definition: gdiobj.h:46
VOID NTAPI BRUSH_vDeleteObject(PVOID pvObject)
Definition: brush.cpp:252
_SEH2_TRY
Definition: create.c:4226
union _ENTRY::_EINFO einfo
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define GDIOBJ_POOL_TAG(type)
Definition: gdiobj.c:134
static PENTRY ENTRY_ReferenceEntryByHandle(HGDIOBJ hobj, FLONG fl)
Definition: gdiobj.c:478
W32KAPI INT APIENTRY NtGdiExtGetObjectW(IN HANDLE hobj, IN INT cjBufferSize, OUT LPVOID lpBuffer)
Definition: gdiobj.c:1326
#define SECTION_ALL_ACCESS
Definition: nt_native.h:1293
ULONG cExclusiveLocks
Definition: win32.h:153
namespace GUID const ADDRINFOEXW ADDRINFOEXW struct timeval OVERLAPPED LPLOOKUPSERVICE_COMPLETION_ROUTINE HANDLE * handle
Definition: sock.c:82
#define SEC_COMMIT
Definition: mmtypes.h:99
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
_In_ FLONG fl
Definition: winddi.h:1279
BOOL NTAPI GDIOBJ_ConvertToStockObj(HGDIOBJ *phObj)
Definition: gdiobj.c:1455
#define FALSE
Definition: types.h:117
Definition: text.h:59
unsigned int BOOL
Definition: ntddk_ex.h:94
static VOID ENTRY_vPushFreeEntry(PENTRY pentFree)
Definition: gdiobj.c:439
BOOL NTAPI DbgGdiHTIntegrityCheck(VOID)
long LONG
Definition: pedump.c:60
#define DBG_LOGEVENT(pslh, type, val)
Definition: gdidebug.h:109
short SHORT
Definition: pedump.c:59
FORCEINLINE void DECREASE_THREAD_LOCK_COUNT(_In_ HANDLE hobj)
Definition: gdiobj.c:79
static TAGREF LPCWSTR LPDWORD LPVOID lpBuffer
Definition: db.cpp:173
#define PsGetCurrentProcess
Definition: psfuncs.h:17
FORCEINLINE VOID ExReleasePushLockExclusive(PEX_PUSH_LOCK PushLock)
Definition: ex.h:1226
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
PGDIOBJ NTAPI GDIOBJ_ShareLockObj(HGDIOBJ hObj, DWORD ExpectedType)
Definition: gdiobj.c:1443
FORCEINLINE ULONG InterlockedReadUlong(_In_ _Interlocked_operand_ ULONG volatile *Source)
Definition: gdiobj.c:55
PVOID NTAPI GDIOBJ_pvGetObjectAttr(POBJ pobj)
Definition: gdiobj.c:1088
PULONG gpaulRefCount
Definition: gdiobj.c:150
#define __analysis_assume(expr)
Definition: sal.h:2893
EX_PUSH_LOCK pushlock
Definition: gdiobj.h:47
#define GDI_HANDLE_IS_STOCKOBJ(h)
Definition: gdi.h:37
#define ExInitializePushLock
Definition: ex.h:987
PsGetCurrentThreadId
Definition: CrNtStubs.h:7
PGDI_HANDLE_TABLE GdiHandleTable
Definition: gdiobj.c:1440
Definition: region.h:7
NTSTATUS NTAPI MmMapViewOfSection(IN PVOID SectionObject, IN PEPROCESS Process, IN OUT PVOID *BaseAddress, IN ULONG_PTR ZeroBits, IN SIZE_T CommitSize, IN OUT PLARGE_INTEGER SectionOffset OPTIONAL, IN OUT PSIZE_T ViewSize, IN SECTION_INHERIT InheritDisposition, IN ULONG AllocationType, IN ULONG Protect)
Definition: section.c:3851
void * PVOID
Definition: retypes.h:9
BOOL NTAPI GDIOBJ_bLockMultipleObjects(IN ULONG ulCount, IN HGDIOBJ *ahObj, OUT PGDIOBJ *apObj, IN UCHAR objt)
Definition: gdiobj.c:1031
#define InterlockedExchangeAdd
Definition: interlocked.h:181
unsigned long FLONG
Definition: ntbasedef.h:366
#define UlongToPtr(u)
Definition: config.h:106
VOID(NTAPI * GDICLEANUPPROC)(PVOID ObjectBody)
Definition: gdiobj.h:33
#define PtrToUlong(u)
Definition: config.h:107
#define GDI_HANDLE_GET_TYPE(h)
Definition: gdi.h:31
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
BOOL NTAPI GDI_CleanupForProcess(struct _EPROCESS *Process)
Definition: gdiobj.c:1548
Status
Definition: gdiplustypes.h:24
FORCEINLINE void INCREASE_THREAD_LOCK_COUNT(_In_ HANDLE hobj)
Definition: gdiobj.c:63
Definition: polytest.cpp:40
VOID NTAPI GDIOBJ_vDeleteObject(POBJ pobj)
Definition: gdiobj.c:1111
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
#define ASSERT(a)
Definition: mode.c:45
static const GDIOBJDELETEPROC apfnDelete[]
Definition: gdiobj.c:197
W32KAPI HANDLE APIENTRY NtGdiCreateClientObj(IN ULONG ulType)
Definition: gdiobj.c:1376
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define ASSERT_SHARED_OBJECT_TYPE(objt)
Definition: gdiobj.c:125
NTSTATUS NTAPI MmCreateSection(OUT PVOID *Section, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, IN PLARGE_INTEGER MaximumSize, IN ULONG SectionPageProtection, IN ULONG AllocationAttributes, IN HANDLE FileHandle OPTIONAL, IN PFILE_OBJECT FileObject OPTIONAL)
Definition: section.c:4341
#define UlongToHandle(ul)
Definition: basetsd.h:97
NTSTATUS NTAPI InitGdiHandleTable(void)
Definition: gdiobj.c:259
Definition: brush.hpp:15
struct _GDI_HANDLE_TABLE GDI_HANDLE_TABLE
#define ObDereferenceObject
Definition: obfuncs.h:203
unsigned short WORD
Definition: ntddk_ex.h:93
static PENTRY ENTRY_pentPopFreeEntry(VOID)
Definition: gdiobj.c:382
unsigned long DWORD
Definition: ntddk_ex.h:95
PGDI_POOL GetBrushAttrPool(VOID)
HACK!
Definition: gdiobj.c:1612
FORCEINLINE VOID IncrementCurrentProcessGdiHandleCount(void)
Definition: gdiobj.c:332
static VOID NTAPI GDIOBJ_vCleanup(PVOID ObjectBody)
Definition: gdiobj.c:238
CODE_SEG("INIT")
Definition: fsrtlpc.c:19
ULONG ulObj
Definition: ntgdihdl.h:245
VOID NTAPI GDIOBJ_vSetObjectAttr(POBJ pobj, PVOID pvObjAttr)
Definition: gdiobj.c:1096
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
VOID NTAPI GDIOBJ_vUnlockObject(POBJ pobj)
Definition: gdiobj.c:880
#define ASSERT_LOCK_ORDER(hobj)
Definition: gdiobj.c:124
NTSTATUS NTAPI PsLookupProcessByProcessId(IN HANDLE ProcessId, OUT PEPROCESS *Process)
Definition: process.c:919
unsigned char UCHAR
Definition: xmlstorage.h:181
#define DBG_DUMP_EVENT_LIST(pslh)
Definition: gdidebug.h:111
DWORD dwThreadId
Definition: fdebug.c:31
#define ASSERT_EXCLUSIVE_OBJECT_TYPE(objt)
Definition: gdiobj.c:126
#define InterlockedDecrement
Definition: armddk.h:52
#define FL_ZERO_MEMORY
Definition: polytest.cpp:58
struct _PATH PATH
VOID NTAPI REGION_vCleanup(PVOID ObjectBody)
Definition: region.c:2452
#define KeEnterCriticalRegion()
Definition: ke_x.h:83
static HGDIOBJ ENTRY_hInsertObject(PENTRY pentry, POBJ pobj, UCHAR objt, ULONG ulOwner)
Definition: gdiobj.c:539
#define InterlockedOr
Definition: interlocked.h:224
#define GDI_OBJ_HMGR_POWNED
Definition: ntgdihdl.h:117
PENTRY gpentHmgr
Definition: gdiobj.c:149
struct _REGION REGION
HGDIOBJ hFree
Definition: ntgdihdl.h:235
#define GDI_OBJECT_TYPE_DONTCARE
Definition: gdi.h:64
static PVOID gpvGdiHdlTblSection
Definition: gdiobj.c:148
#define GDI_OBJECT_STACK_LEVELS
Definition: gdiobj.h:8
static const unsigned RESERVE_ENTRIES_COUNT
Definition: gdiobj.h:11
#define TAG_GDIHNDTBLE
Definition: tags.h:16
VOID NTAPI PALETTE_vCleanup(PVOID ObjectBody)
Definition: palette.c:236
#define _In_
Definition: no_sal2.h:158
void * HGDIOBJ
Definition: windef.h:252
VOID NTAPI DRIVEROBJ_vCleanup(PVOID pObject)
DRIVEROBJ cleanup function.
Definition: driverobj.c:24
ULONG_PTR SIZE_T
Definition: typedefs.h:80
ULONG ulIndex
Definition: symbols.c:92
_SEH2_END
Definition: create.c:4400
#define KeLeaveCriticalRegion()
Definition: ke_x.h:114
#define InterlockedIncrement
Definition: armddk.h:53
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
struct LOOKASIDE_ALIGN _PAGED_LOOKASIDE_LIST PAGED_LOOKASIDE_LIST
unsigned short USHORT
Definition: pedump.c:61
USHORT FullUnique
Definition: ntgdihdl.h:248
Definition: bl.h:1331
#define GDI_HANDLE_COUNT
Definition: gdi.h:12
#define STATUS_NO_MEMORY
Definition: ntstatus.h:260
#define FORCEINLINE
Definition: wdftypes.h:67
PGDIOBJ NTAPI GDIOBJ_TryLockObject(HGDIOBJ hobj, UCHAR objt)
Definition: gdiobj.c:757
POBJ NTAPI GDIOBJ_AllocObjWithHandle(ULONG ObjectType, ULONG cjSize)
Definition: gdiobj.c:1488
#define GDI_OBJ_HMGR_PUBLIC
Definition: ntgdihdl.h:116
unsigned int * PULONG
Definition: retypes.h:1
#define min(a, b)
Definition: monoChain.cc:55
INT APIENTRY PEN_GetObject(PBRUSH pbrushPen, INT cbCount, PLOGPEN pBuffer)
Definition: pen.c:255
HANDLE NTAPI PsGetCurrentProcessId(VOID)
Definition: process.c:1123
VOID NTAPI GDIOBJ_vReferenceObjectByPointer(POBJ pobj)
Definition: gdiobj.c:734
unsigned int UINT
Definition: ndis.h:50
#define NULL
Definition: types.h:112
PVOID NTAPI PsGetCurrentProcessWin32Process(VOID)
Definition: process.c:1183
struct _SURFACE SURFACE
#define PAGE_READONLY
Definition: compat.h:138
#define DPRINT1
Definition: precomp.h:8
static VOID IncrementGdiHandleCount(ULONG ulProcessId)
Definition: gdiobj.c:348
_In_z_ PCWSTR _In_ ULONG ulType
Definition: ntuser.h:36
#define DBG_CLEANUP_EVENT_LIST(pslh)
Definition: gdidebug.h:112
_Must_inspect_result_ _In_ PLARGE_INTEGER _In_ PLARGE_INTEGER _In_ ULONG _In_ PFILE_OBJECT _In_ PVOID Process
Definition: fsrtlfuncs.h:219
#define OUT
Definition: typedefs.h:40
ULONG FASTCALL FontGetObject(PTEXTOBJ plfont, ULONG cjBuffer, PVOID pvBuffer)
Definition: font.c:293
W32KAPI BOOL APIENTRY NtGdiDeleteClientObj(IN HANDLE hobj)
Definition: gdiobj.c:1422
#define GDI_OBJ_HMGR_NONE
Definition: ntgdihdl.h:118
unsigned int ULONG
Definition: retypes.h:1
VOID NTAPI SURFACE_vCleanup(PVOID ObjectBody)
Definition: surface.c:67
_In_ ULONG cjSize
Definition: winddi.h:3634
#define W32KAPI
Definition: ntgdi.h:9
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define ULONG_PTR
Definition: config.h:101
VOID NTAPI GDIOBJ_vSetObjectOwner(POBJ pobj, ULONG ulNewOwner)
Definition: gdiobj.c:965
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
static HBITMAP bitmap
Definition: clipboard.c:1344
_In_ UINT _In_ UINT _In_ PNDIS_PACKET Source
Definition: ndis.h:3167
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:6
union _ENTRY::_OBJECTOWNER ObjectOwner
#define STATUS_SUCCESS
Definition: shellext.h:65
Definition: ntgdihdl.h:230
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1099
static const GDICLEANUPPROC apfnCleanup[]
Definition: gdiobj.c:159
BOOL NTAPI GreSetObjectOwnerEx(HGDIOBJ hobj, ULONG ulOwner, ULONG Flags)
Definition: gdiobj.c:1222
#define DPRINT
Definition: sndvol32.h:71
NTSTATUS NTAPI MmMapViewInSessionSpace(IN PVOID Section, OUT PVOID *MappedBase, IN OUT PSIZE_T ViewSize)
Definition: section.c:3043
struct LOOKASIDE_ALIGN _PAGED_LOOKASIDE_LIST * PPAGED_LOOKASIDE_LIST
signed int * PLONG
Definition: retypes.h:5
static SERVICE_STATUS status
Definition: service.c:31
#define SEC_NO_CHANGE
Definition: mmtypes.h:94
VOID NTAPI DC_vCleanup(PVOID ObjectBody)
Definition: dclife.c:357
POBJ NTAPI GDIOBJ_AllocateObject(UCHAR objt, ULONG cjSize, FLONG fl)
Definition: gdiobj.c:562
INT NTAPI GreGetObject(IN HGDIOBJ hobj, IN INT cbCount, OUT PVOID pvBuffer)
Definition: gdiobj.c:1264
#define APIENTRY
Definition: api.h:79
VOID NTAPI GDIOBJ_vFreeObject(POBJ pobj)
Definition: gdiobj.c:596
LONGLONG QuadPart
Definition: typedefs.h:114
#define InterlockedOr16
Definition: interlocked.h:239
#define PAGE_READWRITE
Definition: nt_native.h:1304
FORCEINLINE BOOLEAN ExTryAcquirePushLockExclusive(PEX_PUSH_LOCK PushLock)
Definition: misc.h:98
#define GDI_HANDLE_STOCK_MASK
Definition: gdi.h:19
#define NT_ASSERT
Definition: rtlfuncs.h:3312
HGDIOBJ NTAPI GDIOBJ_hInsertObject(POBJ pobj, ULONG ulOwner)
Definition: gdiobj.c:912
Definition: ps.c:97