ReactOS  0.4.14-dev-49-gfb4591c
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 INIT_FUNCTION
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 
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 
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 && pentry->einfo.pobj->hHmgr == hobj);
530 
531  return pentry;
532 }
533 
534 static
535 HGDIOBJ
536 ENTRY_hInsertObject(PENTRY pentry, POBJ pobj, UCHAR objt, ULONG ulOwner)
537 {
538  ULONG ulIndex;
539 
540  /* Calculate the handle index */
541  ulIndex = pentry - gpentHmgr;
542 
543  /* Update the fields in the ENTRY */
544  pentry->einfo.pobj = pobj;
545  pentry->Objt = objt & 0x1f;
546  pentry->FullUnique = (pentry->FullUnique & 0xff00) | objt;
547  pentry->ObjectOwner.ulObj = ulOwner;
548 
549  /* Make the handle valid with 1 reference */
552 
553  /* Return the handle */
554  return (HGDIOBJ)(((ULONG_PTR)pentry->FullUnique << 16) | ulIndex);
555 }
556 
557 POBJ
558 NTAPI
560 {
561  POBJ pobj;
562 
563  if (fl & BASEFLAG_LOOKASIDE)
564  {
565  /* Allocate the object from a lookaside list */
566  pobj = ExAllocateFromPagedLookasideList(&gpaLookasideList[objt & 0x1f]);
567  }
568  else
569  {
570  /* Allocate the object from paged pool */
572  }
573 
574  if (!pobj) return NULL;
575 
576  /* Initialize the object */
577  RtlZeroMemory(pobj, cjSize);
578  pobj->hHmgr = (HGDIOBJ)((ULONG_PTR)objt << 16);
579  pobj->cExclusiveLock = 0;
580  pobj->ulShareCount = 1;
581  pobj->BaseFlags = fl & 0xffff;
582  DBG_INITLOG(&pobj->slhLog);
583  DBG_LOGEVENT(&pobj->slhLog, EVENT_ALLOCATE, 0);
584 #if DBG_ENABLE_GDIOBJ_BACKTRACES
585  DbgCaptureStackBackTace(pobj->apvBackTrace, 1, GDI_OBJECT_STACK_LEVELS);
586 #endif /* GDI_DEBUG */
587 
588  return pobj;
589 }
590 
591 VOID
592 NTAPI
594 {
595  UCHAR objt;
596 
597  DBG_CLEANUP_EVENT_LIST(&pobj->slhLog);
598 
599  /* Get the object type */
600  objt = ((ULONG_PTR)pobj->hHmgr >> 16) & 0x1f;
601 
602  /* Check if we have a delete procedure (for C++ based objects) */
603  if (apfnDelete[objt] != NULL)
604  {
605  /* Invoke the delete procedure */
606  apfnDelete[objt](pobj);
607  }
608  else
609  {
610  /* Call the cleanup procedure */
611  NT_ASSERT(apfnCleanup[objt]);
612  apfnCleanup[objt](pobj);
613 
614  /* Check if the object is allocated from a lookaside list */
615  if (pobj->BaseFlags & BASEFLAG_LOOKASIDE)
616  {
617  ExFreeToPagedLookasideList(&gpaLookasideList[objt], pobj);
618  }
619  else
620  {
621  ExFreePoolWithTag(pobj, GDIOBJ_POOL_TAG(objt));
622  }
623  }
624 }
625 
626 VOID
627 NTAPI
629 {
630  ULONG cRefs, ulIndex;
631 
632  /* Calculate the index */
634 
635  /* Check if the object has a handle */
636  if (ulIndex)
637  {
638  /* Decrement reference count */
639  if ((gpaulRefCount[ulIndex] & REF_MASK_COUNT) == 0)
640  {
641  DBG_DUMP_EVENT_LIST(&pobj->slhLog);
642  }
645  DBG_LOGEVENT(&pobj->slhLog, EVENT_DEREFERENCE, cRefs);
646 
647  /* Check if we reached 0 and handle bit is not set */
648  if ((cRefs & REF_MASK_INUSE) == 0)
649  {
650  /* Make sure it's ok to delete the object */
652 
653  /* Check if the handle was process owned */
654  if (gpentHmgr[ulIndex].ObjectOwner.ulObj != GDI_OBJ_HMGR_PUBLIC &&
656  {
657  /* Decrement the process handle count */
658  ASSERT(gpentHmgr[ulIndex].ObjectOwner.ulObj ==
661  }
662 
663  /* Push entry to the free list */
665 
666  /* Free the object */
667  GDIOBJ_vFreeObject(pobj);
668  }
669  }
670  else
671  {
672  /* Decrement the objects reference count */
673  ASSERT(pobj->ulShareCount > 0);
674  cRefs = InterlockedDecrement((LONG*)&pobj->ulShareCount);
675  DBG_LOGEVENT(&pobj->slhLog, EVENT_DEREFERENCE, cRefs);
676 
677  /* Check if we reached 0 */
678  if (cRefs == 0)
679  {
680  /* Free the object */
681  GDIOBJ_vFreeObject(pobj);
682  }
683  }
684 }
685 
686 POBJ
687 NTAPI
689  HGDIOBJ hobj,
690  UCHAR objt)
691 {
692  PENTRY pentry;
693  POBJ pobj;
694 
695  /* Check if the handle type matches */
697  if ((((ULONG_PTR)hobj >> 16) & 0x1f) != objt)
698  {
699  DPRINT("GDIOBJ: Wrong type. handle=%p, type=%x\n", hobj, objt);
700  return NULL;
701  }
702 
703  /* Reference the handle entry */
704  pentry = ENTRY_ReferenceEntryByHandle(hobj, 0);
705  if (!pentry)
706  {
707  DPRINT("GDIOBJ: Requested handle 0x%p is not valid.\n", hobj);
708  return NULL;
709  }
710 
711  /* Get the pointer to the BASEOBJECT */
712  pobj = pentry->einfo.pobj;
713 
714  /* Check if the object is exclusively locked */
715  if (pobj->cExclusiveLock != 0)
716  {
717  DPRINT1("GDIOBJ: Cannot reference object %p with exclusive lock.\n", hobj);
719  DBG_DUMP_EVENT_LIST(&pobj->slhLog);
720  return NULL;
721  }
722 
723  DBG_LOGEVENT(&pobj->slhLog, EVENT_REFERENCE, gpaulRefCount[pentry - gpentHmgr]);
724 
725  /* All is well, return the object */
726  return pobj;
727 }
728 
729 VOID
730 NTAPI
732 {
733  ULONG cRefs;
734 
735  /* Check if the object has a handle */
736  if (GDI_HANDLE_GET_INDEX(pobj->hHmgr))
737  {
738  /* Increase the handle's reference count */
742  }
743  else
744  {
745  /* Increase the object's reference count */
746  cRefs = InterlockedIncrement((LONG*)&pobj->ulShareCount);
747  }
748 
749  DBG_LOGEVENT(&pobj->slhLog, EVENT_REFERENCE, cRefs);
750 }
751 
752 PGDIOBJ
753 NTAPI
755  HGDIOBJ hobj,
756  UCHAR objt)
757 {
758  PENTRY pentry;
759  POBJ pobj;
761 
762  /* Check if the handle type matches */
764  if ((((ULONG_PTR)hobj >> 16) & 0x1f) != objt)
765  {
766  DPRINT("Wrong object type: hobj=0x%p, objt=0x%x\n", hobj, objt);
767  return NULL;
768  }
769 
770  /* Make sure lock order is correct */
771  ASSERT_LOCK_ORDER(objt);
772 
773  /* Reference the handle entry */
774  pentry = ENTRY_ReferenceEntryByHandle(hobj, 0);
775  if (!pentry)
776  {
777  DPRINT("GDIOBJ: Requested handle 0x%p is not valid.\n", hobj);
778  return NULL;
779  }
780 
781  /* Get the pointer to the BASEOBJECT */
782  pobj = pentry->einfo.pobj;
783 
784  /* Check if we already own the lock */
786  if (pobj->dwThreadId != dwThreadId)
787  {
788  /* Disable APCs and try acquiring the push lock */
791  {
792  ULONG cRefs, ulIndex;
793  /* Already owned. Clean up and leave. */
795 
796  /* Calculate the index */
798 
799  /* Decrement reference count */
802  ASSERT(cRefs & REF_MASK_VALID);
803 
804  return NULL;
805  }
806 
807  /* Set us as lock owner */
808  ASSERT(pobj->dwThreadId == 0);
809  pobj->dwThreadId = dwThreadId;
810  }
811 
812  /* Increase lock count */
813  pobj->cExclusiveLock++;
815  DBG_LOGEVENT(&pobj->slhLog, EVENT_LOCK, 0);
816 
817  /* Return the object */
818  return pobj;
819 }
820 
821 PGDIOBJ
822 NTAPI
824  HGDIOBJ hobj,
825  UCHAR objt)
826 {
827  PENTRY pentry;
828  POBJ pobj;
830 
831  /* Check if the handle type matches */
833  if ((((ULONG_PTR)hobj >> 16) & 0x1f) != objt)
834  {
835  DPRINT("Wrong object type: hobj=0x%p, objt=0x%x\n", hobj, objt);
836  return NULL;
837  }
838 
839  /* Make sure lock order is correct */
840  ASSERT_LOCK_ORDER(objt);
841 
842  /* Reference the handle entry */
843  pentry = ENTRY_ReferenceEntryByHandle(hobj, 0);
844  if (!pentry)
845  {
846  DPRINT("GDIOBJ: Requested handle 0x%p is not valid.\n", hobj);
847  return NULL;
848  }
849 
850  /* Get the pointer to the BASEOBJECT */
851  pobj = pentry->einfo.pobj;
852 
853  /* Check if we already own the lock */
855  if (pobj->dwThreadId != dwThreadId)
856  {
857  /* Disable APCs and acquire the push lock */
860 
861  /* Set us as lock owner */
862  ASSERT(pobj->dwThreadId == 0);
863  pobj->dwThreadId = dwThreadId;
864  }
865 
866  /* Increase lock count */
867  pobj->cExclusiveLock++;
869  DBG_LOGEVENT(&pobj->slhLog, EVENT_LOCK, 0);
870 
871  /* Return the object */
872  return pobj;
873 }
874 
875 VOID
876 NTAPI
878 {
879  ULONG cRefs, ulIndex;
880  ASSERT(pobj->cExclusiveLock > 0);
881 
882  /* Decrease lock count */
883  pobj->cExclusiveLock--;
885  DBG_LOGEVENT(&pobj->slhLog, EVENT_UNLOCK, 0);
886 
887  /* Check if this was the last lock */
888  if (pobj->cExclusiveLock == 0)
889  {
890  /* Reset lock owner */
891  pobj->dwThreadId = 0;
892 
893  /* Release the pushlock and reenable APCs */
896  }
897 
898  /* Calculate the index */
900 
901  /* Decrement reference count */
904  ASSERT(cRefs & REF_MASK_VALID);
905 }
906 
907 HGDIOBJ
908 NTAPI
910  POBJ pobj,
911  ULONG ulOwner)
912 {
913  PENTRY pentry;
914  UCHAR objt;
915 
916  /* Must have no handle and only one reference */
917  ASSERT(GDI_HANDLE_GET_INDEX(pobj->hHmgr) == 0);
918  ASSERT(pobj->cExclusiveLock == 0);
919  ASSERT(pobj->ulShareCount == 1);
920 
921  /* Get a free handle entry */
922  pentry = ENTRY_pentPopFreeEntry();
923  if (!pentry)
924  {
925  DPRINT1("GDIOBJ: Could not get a free entry.\n");
926  return NULL;
927  }
928 
929  /* Make the object exclusively locked */
933  pobj->cExclusiveLock = 1;
936 
937  /* Get object type from the hHmgr field */
938  objt = ((ULONG_PTR)pobj->hHmgr >> 16) & 0xff;
939  ASSERT(objt != GDIObjType_DEF_TYPE);
940 
941  /* Check if current process is requested owner */
942  if (ulOwner == GDI_OBJ_HMGR_POWNED)
943  {
944  /* Increment the process handle count */
946 
947  /* Use Process id */
949  }
950 
951  /* Insert the object into the handle table */
952  pobj->hHmgr = ENTRY_hInsertObject(pentry, pobj, objt, ulOwner);
953 
954  /* Return the handle */
955  DPRINT("GDIOBJ: Created handle: %p\n", pobj->hHmgr);
956  DBG_LOGEVENT(&pobj->slhLog, EVENT_CREATE_HANDLE, 0);
957  return pobj->hHmgr;
958 }
959 
960 VOID
961 NTAPI
963  POBJ pobj,
964  ULONG ulNewOwner)
965 {
966  PENTRY pentry;
967  ULONG ulOldOwner;
968 
969  /* This is a ugly HACK, needed to fix IntGdiSetDCOwnerEx */
970  if (GDI_HANDLE_IS_STOCKOBJ(pobj->hHmgr))
971  {
972  DPRINT("Trying to set ownership of stock object %p to %lx\n", pobj->hHmgr, ulNewOwner);
973  return;
974  }
975 
976  /* Get the handle entry */
978  pentry = &gpentHmgr[GDI_HANDLE_GET_INDEX(pobj->hHmgr)];
979 
980  /* Check if the new owner is the same as the old one */
981  ulOldOwner = pentry->ObjectOwner.ulObj;
982  if (ulOldOwner == ulNewOwner)
983  {
984  /* Nothing to do */
985  return;
986  }
987 
988  /* Is the current process requested? */
989  if (ulNewOwner == GDI_OBJ_HMGR_POWNED)
990  {
991  /* Use process id */
992  ulNewOwner = HandleToUlong(PsGetCurrentProcessId());
993  }
994 
995  // HACK
996  if (ulNewOwner == GDI_OBJ_HMGR_NONE)
997  ulNewOwner = GDI_OBJ_HMGR_PUBLIC;
998 
999  /* Was the object process owned? */
1000  if ((ulOldOwner != GDI_OBJ_HMGR_PUBLIC) &&
1001  (ulOldOwner != GDI_OBJ_HMGR_NONE))
1002  {
1003  /* Decrement the previous owners handle count */
1004  DecrementGdiHandleCount(ulOldOwner);
1005  }
1006 
1007  /* Is the new owner a process? */
1008  if ((ulNewOwner != GDI_OBJ_HMGR_PUBLIC) &&
1009  (ulNewOwner != GDI_OBJ_HMGR_NONE))
1010  {
1011  /* Increment the new owners handle count */
1012  IncrementGdiHandleCount(ulNewOwner);
1013  }
1014  else
1015  {
1016  /* Make sure we don't leak user mode memory */
1017  NT_ASSERT(pentry->pUser == NULL);
1018  }
1019 
1020  /* Set new owner */
1021  pentry->ObjectOwner.ulObj = ulNewOwner;
1022  DBG_LOGEVENT(&pobj->slhLog, EVENT_SET_OWNER, 0);
1023 }
1024 
1025 /* Locks 2 or 3 objects at a time */
1026 BOOL
1027 NTAPI
1029  IN ULONG ulCount,
1030  IN HGDIOBJ* ahObj,
1031  OUT PGDIOBJ* apObj,
1032  IN UCHAR objt)
1033 {
1034  UINT auiIndices[3] = {0, 1, 2};
1035  UINT i, j, tmp;
1036 
1037  ASSERT(ulCount <= 3);
1038 
1039  /* Sort the handles */
1040  for (i = 0; i < ulCount - 1; i++)
1041  {
1042  for (j = i + 1; j < ulCount; j++)
1043  {
1044  if ((ULONG_PTR)ahObj[auiIndices[i]] <
1045  (ULONG_PTR)ahObj[auiIndices[j]])
1046  {
1047  tmp = auiIndices[i];
1048  auiIndices[i] = auiIndices[j];
1049  auiIndices[j] = tmp;
1050  }
1051  }
1052  }
1053 
1054  /* Lock the objects in safe order */
1055  for (i = 0; i < ulCount; i++)
1056  {
1057  /* Skip NULL handles */
1058  if (ahObj[auiIndices[i]] == NULL)
1059  {
1060  apObj[auiIndices[i]] = NULL;
1061  continue;
1062  }
1063 
1064  /* Lock the object */
1065  apObj[auiIndices[i]] = GDIOBJ_LockObject(ahObj[auiIndices[i]], objt);
1066 
1067  /* Check for failure */
1068  if (apObj[auiIndices[i]] == NULL)
1069  {
1070  /* Cleanup */
1071  while (i--)
1072  {
1073  if (apObj[auiIndices[i]])
1074  GDIOBJ_vUnlockObject(apObj[auiIndices[i]]);
1075  }
1076  return FALSE;
1077  }
1078  }
1079 
1080  return TRUE;
1081 }
1082 
1083 PVOID
1084 NTAPI
1086 {
1088  return gpentHmgr[ulIndex].pUser;
1089 }
1090 
1091 VOID
1092 NTAPI
1094 {
1095  ULONG ulIndex;
1096 
1097  ASSERT(pobj->hHmgr);
1098 
1099  /* Get the handle index */
1101 
1102  /* Set pointer to the usermode attribute */
1103  gpentHmgr[ulIndex].pUser = pvObjAttr;
1104 }
1105 
1106 VOID
1107 NTAPI
1109 {
1110  ULONG ulIndex;
1111 
1112  /* Set the object's delete flag */
1114  DBG_LOGEVENT(&pobj->slhLog, EVENT_DELETE, 0);
1115 
1116  /* Get the handle index */
1118  if (ulIndex)
1119  {
1120  /* Reset the handle valid bit */
1122 
1123  /* Check if the object is exclusively locked */
1124  if (pobj->cExclusiveLock != 0)
1125  {
1126  /* Reset lock owner and lock count */
1127  pobj->dwThreadId = 0;
1128  pobj->cExclusiveLock = 0;
1129 
1130  /* Release the pushlock and reenable APCs */
1134  }
1135  }
1136 
1137  /* Dereference the object (will take care of deletion) */
1139 }
1140 
1141 BOOL
1142 NTAPI
1144 {
1145  PENTRY pentry;
1146 
1147  pentry = ENTRY_ReferenceEntryByHandle(hobj, 0);
1148  if (!pentry) return FALSE;
1150  return TRUE;
1151 }
1152 
1153 BOOL
1154 NTAPI
1156 {
1157  PENTRY pentry;
1158 
1159  /* Check for stock objects */
1160  if (GDI_HANDLE_IS_STOCKOBJ(hobj))
1161  {
1162  DPRINT1("GreDeleteObject: Cannot delete stock object %p.\n", hobj);
1163  return FALSE;
1164  }
1165 
1166  /* Reference the handle entry */
1167  pentry = ENTRY_ReferenceEntryByHandle(hobj, 0);
1168  if (!pentry)
1169  {
1170  DPRINT1("GreDeleteObject: Trying to delete invalid object %p\n", hobj);
1171  return FALSE;
1172  }
1173 
1174  /* Check for public owner */
1175  if (pentry->ObjectOwner.ulObj == GDI_OBJ_HMGR_PUBLIC)
1176  {
1177  DPRINT1("GreDeleteObject: Trying to delete global object %p\n", hobj);
1179  return FALSE;
1180  }
1181 
1182  /* Delete the object */
1183  GDIOBJ_vDeleteObject(pentry->einfo.pobj);
1184  return TRUE;
1185 }
1186 
1187 ULONG
1188 NTAPI
1190 {
1191  ULONG ulIndex, ulOwner;
1192 
1193  /* Get the handle index */
1194  ulIndex = GDI_HANDLE_GET_INDEX(hobj);
1195 
1196  /* Check if the handle is valid */
1197  if (ulIndex >= GDI_HANDLE_COUNT ||
1199  ((ULONG_PTR)hobj >> 16) != gpentHmgr[ulIndex].FullUnique)
1200  {
1201  DPRINT1("GreGetObjectOwner: invalid handle 0x%p.\n", hobj);
1202  return GDI_OBJ_HMGR_RESTRICTED;
1203  }
1204 
1205  /* Get the object owner */
1206  ulOwner = gpentHmgr[ulIndex].ObjectOwner.ulObj;
1207 
1208  if (ulOwner == HandleToUlong(PsGetCurrentProcessId()))
1209  return GDI_OBJ_HMGR_POWNED;
1210 
1211  if (ulOwner == GDI_OBJ_HMGR_PUBLIC)
1212  return GDI_OBJ_HMGR_PUBLIC;
1213 
1214  return GDI_OBJ_HMGR_RESTRICTED;
1215 }
1216 
1217 BOOL
1218 NTAPI
1220  HGDIOBJ hobj,
1221  ULONG ulOwner,
1222  ULONG Flags)
1223 {
1224  PENTRY pentry;
1225 
1226  /* Check for stock objects */
1227  if (GDI_HANDLE_IS_STOCKOBJ(hobj))
1228  {
1229  DPRINT("GreSetObjectOwner: Got stock object %p\n", hobj);
1230  return FALSE;
1231  }
1232 
1233  /* Reference the handle entry */
1234  pentry = ENTRY_ReferenceEntryByHandle(hobj, Flags);
1235  if (!pentry)
1236  {
1237  DPRINT("GreSetObjectOwner: Invalid handle 0x%p.\n", hobj);
1238  return FALSE;
1239  }
1240 
1241  /* Call internal function */
1242  GDIOBJ_vSetObjectOwner(pentry->einfo.pobj, ulOwner);
1243 
1244  /* Dereference the object */
1246 
1247  return TRUE;
1248 }
1249 
1250 BOOL
1251 NTAPI
1253  HGDIOBJ hobj,
1254  ULONG ulOwner)
1255 {
1256  return GreSetObjectOwnerEx(hobj, ulOwner, 0);
1257 }
1258 
1259 INT
1260 NTAPI
1262  IN HGDIOBJ hobj,
1263  IN INT cbCount,
1264  OUT PVOID pvBuffer)
1265 {
1266  PVOID pvObj;
1267  UCHAR objt;
1268  INT iResult = 0;
1269 
1270  /* Verify object type */
1271  objt = ((ULONG_PTR)hobj >> 16) & 0x1f;
1272  if (objt != GDIObjType_BRUSH_TYPE &&
1273  objt != GDIObjType_SURF_TYPE &&
1274  objt != GDIObjType_LFONT_TYPE &&
1275  objt != GDIObjType_PAL_TYPE)
1276  {
1277  DPRINT1("GreGetObject: Invalid object type\n");
1278  return 0;
1279  }
1280 
1281  pvObj = GDIOBJ_ReferenceObjectByHandle(hobj, objt);
1282  if (!pvObj)
1283  {
1284  DPRINT("GreGetObject: Could not lock object\n");
1285  return 0;
1286  }
1287 
1288  switch (GDI_HANDLE_GET_TYPE(hobj))
1289  {
1292  iResult = PEN_GetObject(pvObj, cbCount, pvBuffer);
1293  break;
1294 
1296  iResult = BRUSH_GetObject(pvObj, cbCount, pvBuffer);
1297  break;
1298 
1300  iResult = BITMAP_GetObject(pvObj, cbCount, pvBuffer);
1301  break;
1302 
1304  iResult = FontGetObject(pvObj, cbCount, pvBuffer);
1305  break;
1306 
1308  iResult = PALETTE_GetObject(pvObj, cbCount, pvBuffer);
1309  break;
1310 
1311  default:
1312  DPRINT1("GDI object type of 0x%p not implemented\n", hobj);
1313  break;
1314  }
1315 
1317  return iResult;
1318 }
1319 
1320 W32KAPI
1321 INT
1322 APIENTRY
1324  IN HANDLE hobj,
1325  IN INT cjBufferSize,
1327 {
1328  UINT iResult, cjMaxSize;
1329  union
1330  {
1331  BITMAP bitmap;
1332  DIBSECTION dibsection;
1333  LOGPEN logpen;
1334  LOGBRUSH logbrush;
1335  LOGFONTW logfontw;
1336  EXTLOGFONTW extlogfontw;
1337  ENUMLOGFONTEXDVW enumlogfontexdvw;
1338  } object;
1339 
1340  /* Normalize to the largest supported object size */
1341  cjMaxSize = min((UINT)cjBufferSize, sizeof(object));
1342 
1343  /* Now do the actual call */
1344  iResult = GreGetObject(hobj, cjMaxSize, lpBuffer ? &object : NULL);
1345 
1346  /* Check if we have a buffer and data */
1347  if ((lpBuffer != NULL) && (iResult != 0))
1348  {
1349  /* Enter SEH for buffer transfer */
1350  _SEH2_TRY
1351  {
1352  /* Probe the buffer and copy it */
1353  cjMaxSize = min(cjMaxSize, iResult);
1354  ProbeForWrite(lpBuffer, cjMaxSize, sizeof(WORD));
1355  RtlCopyMemory(lpBuffer, &object, cjMaxSize);
1356  }
1358  {
1359  /* Clear the return value.
1360  * Do *NOT* set last error here! */
1361  iResult = 0;
1362  }
1363  _SEH2_END;
1364  }
1365 
1366  /* Return the count */
1367  return iResult;
1368 }
1369 
1370 W32KAPI
1371 HANDLE
1372 APIENTRY
1374  IN ULONG ulType)
1375 {
1376  POBJ pObject;
1377  HANDLE handle;
1378 
1379  /* Check if ulType is valid */
1383  {
1384  DPRINT1("NtGdiCreateClientObj: Invalid object type 0x%lx.\n", ulType);
1385  return NULL;
1386  }
1387 
1388  /* Allocate a new object */
1390  sizeof(CLIENTOBJ),
1392  if (!pObject)
1393  {
1394  DPRINT1("NtGdiCreateClientObj: Could not allocate a clientobj.\n");
1395  return NULL;
1396  }
1397 
1398  /* Set the real object type */
1400 
1401  /* Create a handle */
1403  if (!handle)
1404  {
1405  DPRINT1("NtGdiCreateClientObj: Could not create a handle.\n");
1406  GDIOBJ_vFreeObject(pObject);
1407  return NULL;
1408  }
1409 
1410  /* Unlock it */
1411  GDIOBJ_vUnlockObject(pObject);
1412 
1413  return handle;
1414 }
1415 
1416 W32KAPI
1417 BOOL
1418 APIENTRY
1420  IN HANDLE hobj)
1421 {
1422  /* We first need to get the real type from the handle */
1424 
1425  /* Check if it's really a CLIENTOBJ */
1427  {
1428  /* FIXME: SetLastError? */
1429  return FALSE;
1430  }
1431 
1432  return GreDeleteObject(hobj);
1433 }
1434 
1435 
1436 
1438 
1439 PGDIOBJ NTAPI
1440 GDIOBJ_ShareLockObj(HGDIOBJ hObj, DWORD ExpectedType)
1441 {
1442  if (ExpectedType == GDI_OBJECT_TYPE_DONTCARE)
1443  ExpectedType = GDI_HANDLE_GET_TYPE(hObj);
1444  return GDIOBJ_ReferenceObjectByHandle(hObj, (ExpectedType >> 16) & 0x1f);
1445 }
1446 
1447 // This function is not safe to use with concurrent deleting attempts
1448 // That shouldn't be a problem, since we don't have any processes yet,
1449 // that could delete the handle
1450 BOOL
1451 NTAPI
1453 {
1454  PENTRY pentry;
1455  POBJ pobj;
1456 
1457  /* Reference the handle entry */
1458  pentry = ENTRY_ReferenceEntryByHandle(*phObj, 0);
1459  if (!pentry)
1460  {
1461  DPRINT1("GDIOBJ: Requested handle 0x%p is not valid.\n", *phObj);
1462  return FALSE;
1463  }
1464 
1465  /* Update the entry */
1466  pentry->FullUnique |= GDI_ENTRY_STOCK_MASK;
1467  pentry->ObjectOwner.ulObj = 0;
1468 
1469  /* Get the pointer to the BASEOBJECT */
1470  pobj = pentry->einfo.pobj;
1471 
1472  /* Calculate the new handle */
1473  pobj->hHmgr = (HGDIOBJ)((ULONG_PTR)pobj->hHmgr | GDI_HANDLE_STOCK_MASK);
1474 
1475  /* Return the new handle */
1476  *phObj = pobj->hHmgr;
1477 
1478  /* Dereference the handle */
1480 
1481  return TRUE;
1482 }
1483 
1484 POBJ NTAPI
1486 {
1487  POBJ pobj;
1488  FLONG fl = 0;
1489  UCHAR objt = (ObjectType >> 16) & 0xFF;
1490 
1491  if ((objt == GDIObjType_DC_TYPE && cjSize == sizeof(DC)) ||
1492  (objt == GDIObjType_PAL_TYPE && cjSize == sizeof(PALETTE)) ||
1493  (objt == GDIObjType_RGN_TYPE && cjSize == sizeof(REGION)) ||
1494  (objt == GDIObjType_SURF_TYPE && cjSize == sizeof(SURFACE)) ||
1495  (objt == GDIObjType_PATH_TYPE && cjSize == sizeof(PATH)))
1496  {
1498  }
1499 
1500  pobj = GDIOBJ_AllocateObject(objt, cjSize, fl);
1501  if (!pobj)
1502  {
1503  return NULL;
1504  }
1505 
1507  {
1508  GDIOBJ_vFreeObject(pobj);
1509  return NULL;
1510  }
1511  return pobj;
1512 }
1513 
1514 PVOID NTAPI
1516 {
1517  PVOID pvMappedView = NULL;
1518  NTSTATUS Status;
1519  LARGE_INTEGER liOffset;
1520  SIZE_T cjViewSize = sizeof(GDI_HANDLE_TABLE);
1521 
1522  liOffset.QuadPart = 0;
1523 
1525  ASSERT(pProcess != NULL);
1526 
1528  pProcess,
1529  &pvMappedView,
1530  0,
1531  0,
1532  &liOffset,
1533  &cjViewSize,
1534  ViewUnmap,
1535  SEC_NO_CHANGE,
1536  PAGE_READONLY);
1537 
1538  if (!NT_SUCCESS(Status))
1539  return NULL;
1540 
1541  return pvMappedView;
1542 }
1543 
1544 BOOL NTAPI
1546 {
1547  PENTRY pentry;
1548  ULONG ulIndex;
1549  DWORD dwProcessId;
1550  PPROCESSINFO ppi;
1551 
1552  DPRINT("CleanupForProcess prochandle %p Pid %p\n",
1553  Process, Process->UniqueProcessId);
1554 
1556 
1557  /* Get the current process Id */
1558  dwProcessId = PtrToUlong(PsGetCurrentProcessId());
1559 
1560  /* Loop all handles in the handle table */
1562  {
1563  pentry = &gpentHmgr[ulIndex];
1564 
1565  /* Check if the object is owned by the process */
1566  if (pentry->ObjectOwner.ulObj == dwProcessId)
1567  {
1568  ASSERT(pentry->einfo.pobj->cExclusiveLock == 0);
1569 
1570  /* Reference the object and delete it */
1572  GDIOBJ_vDeleteObject(pentry->einfo.pobj);
1573  }
1574  }
1575 
1576 #if DBG
1578 #endif
1579 
1581  DPRINT("Completed cleanup for process %p\n", Process->UniqueProcessId);
1582  if (ppi->GDIHandleCount != 0)
1583  {
1584  DPRINT1("Leaking %d handles!\n", ppi->GDIHandleCount);
1585  ASSERT(FALSE);
1586  }
1587 
1588  /* Loop all handles in the handle table */
1590  {
1591  pentry = &gpentHmgr[ulIndex];
1592 
1593  /* Check if the object is owned by the process */
1594  if (pentry->ObjectOwner.ulObj == dwProcessId)
1595  {
1596  DPRINT1("Leaking object. Index=%lx, type=0x%x, refcount=%lx\n",
1597  ulIndex, pentry->Objt, gpaulRefCount[ulIndex]);
1598  DBG_DUMP_EVENT_LIST(&pentry->einfo.pobj->slhLog);
1599  //DBG_CLEANUP_EVENT_LIST(&pentry->einfo.pobj->slhLog);
1600  ASSERT(FALSE);
1601  }
1602  }
1603 
1604  return TRUE;
1605 }
1606 
1608 PGDI_POOL
1610 {
1611  PPROCESSINFO ppi;
1612 
1614  NT_ASSERT(ppi != NULL);
1615 
1616  return ppi->pPoolBrushAttr;
1617 }
1618 
1619 /* 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:1022
#define IN
Definition: typedefs.h:38
PGDIOBJ NTAPI GDIOBJ_LockObject(HGDIOBJ hobj, UCHAR objt)
Definition: gdiobj.c:823
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:1252
#define InterlockedAnd
Definition: interlocked.h:62
namespace GUID const ADDRINFOEXW ADDRINFOEXW struct timeval OVERLAPPED LPLOOKUPSERVICE_COMPLETION_ROUTINE HANDLE * handle
Definition: sock.c:82
BOOL NTAPI GreDeleteObject(HGDIOBJ hobj)
Definition: gdiobj.c:1155
#define TRUE
Definition: types.h:120
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
struct _GDI_POOL * pPoolBrushAttr
Definition: win32.h:283
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:274
#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:1143
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:688
static int cbCount
Definition: fiber.c:42
#define _Interlocked_operand_
Definition: no_sal2.h:309
#define GDITAG_HMGR_LOOKASIDE_START
Definition: tags.h:130
INT APIENTRY BITMAP_GetObject(SURFACE *psurf, INT Count, LPVOID buffer)
Definition: bitmaps.c:766
#define DBG_INITLOG(pslh)
Definition: gdidebug.h:110
INIT_FUNCTION NTSTATUS NTAPI InitGdiHandleTable(void)
Definition: gdiobj.c:259
#define DBG_UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:325
UCHAR Objt
Definition: ntgdihdl.h:249
static PPAGED_LOOKASIDE_LIST gpaLookasideList
Definition: gdiobj.c:153
PVOID NTAPI GDI_MapHandleTable(PEPROCESS pProcess)
Definition: gdiobj.c:1515
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
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:628
#define GDI_ENTRY_STOCK_MASK
Definition: ntgdihdl.h:33
VOID NTAPI ObDereferenceObject(IN PVOID Object)
Definition: obref.c:375
USHORT cExclusiveLock
Definition: gdiobj.h:45
ULONG NTAPI GreGetObjectOwner(HGDIOBJ hobj)
Definition: gdiobj.c:1189
volatile ULONG gulFirstFree
Definition: gdiobj.c:151
HGDIOBJ hHmgr
Definition: gdiobj.h:40
int32_t INT
Definition: typedefs.h:56
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:4250
union _ENTRY::_EINFO einfo
uint32_t ULONG_PTR
Definition: typedefs.h:63
#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:1323
#define SECTION_ALL_ACCESS
Definition: nt_native.h:1293
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
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
ULONG cExclusiveLocks
Definition: win32.h:152
#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:1452
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:1238
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
PGDIOBJ NTAPI GDIOBJ_ShareLockObj(HGDIOBJ hObj, DWORD ExpectedType)
Definition: gdiobj.c:1440
FORCEINLINE ULONG InterlockedReadUlong(_In_ _Interlocked_operand_ ULONG volatile *Source)
Definition: gdiobj.c:55
PVOID NTAPI GDIOBJ_pvGetObjectAttr(POBJ pobj)
Definition: gdiobj.c:1085
PULONG gpaulRefCount
Definition: gdiobj.c:150
#define __analysis_assume(expr)
Definition: sal.h:2893
smooth NULL
Definition: ftsmooth.c:416
EX_PUSH_LOCK pushlock
Definition: gdiobj.h:47
#define GDI_HANDLE_IS_STOCKOBJ(h)
Definition: gdi.h:37
#define FORCEINLINE
Definition: ntbasedef.h:221
void DPRINT(...)
Definition: polytest.cpp:61
#define ExInitializePushLock
Definition: ex.h:999
PsGetCurrentThreadId
Definition: CrNtStubs.h:7
PGDI_HANDLE_TABLE GdiHandleTable
Definition: gdiobj.c:1437
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:4502
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:1028
#define InterlockedExchangeAdd
Definition: interlocked.h:181
unsigned long FLONG
Definition: ntbasedef.h:373
#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:1545
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:1108
static const GDIOBJDELETEPROC apfnDelete[]
Definition: gdiobj.c:197
W32KAPI HANDLE APIENTRY NtGdiCreateClientObj(IN ULONG ulType)
Definition: gdiobj.c:1373
#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:4975
#define UlongToHandle(ul)
Definition: basetsd.h:97
Definition: brush.hpp:15
struct _GDI_HANDLE_TABLE GDI_HANDLE_TABLE
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:1609
FORCEINLINE VOID IncrementCurrentProcessGdiHandleCount(void)
Definition: gdiobj.c:332
static VOID NTAPI GDIOBJ_vCleanup(PVOID ObjectBody)
Definition: gdiobj.c:238
ULONG ulObj
Definition: ntgdihdl.h:245
VOID NTAPI GDIOBJ_vSetObjectAttr(POBJ pobj, PVOID pvObjAttr)
Definition: gdiobj.c:1093
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
VOID NTAPI GDIOBJ_vUnlockObject(POBJ pobj)
Definition: gdiobj.c:877
#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:536
#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
Status
Definition: gdiplustypes.h:24
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:204
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:78
ULONG ulIndex
Definition: symbols.c:92
_SEH2_END
Definition: create.c:4424
#define KeLeaveCriticalRegion()
Definition: ke_x.h:114
#define InterlockedIncrement
Definition: armddk.h:53
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:246
PGDIOBJ NTAPI GDIOBJ_TryLockObject(HGDIOBJ hobj, UCHAR objt)
Definition: gdiobj.c:754
POBJ NTAPI GDIOBJ_AllocObjWithHandle(ULONG ObjectType, ULONG cjSize)
Definition: gdiobj.c:1485
#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:731
unsigned int UINT
Definition: ndis.h:50
PVOID NTAPI PsGetCurrentProcessWin32Process(VOID)
Definition: process.c:1183
struct _SURFACE SURFACE
#define PAGE_READONLY
Definition: compat.h:127
#define DPRINT1
Definition: precomp.h:8
_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
FORCEINLINE VOID DecrementGdiHandleCount(ULONG ulProcessId)
Definition: gdiobj.c:365
#define OUT
Definition: typedefs.h:39
FORCEINLINE VOID IncrementGdiHandleCount(ULONG ulProcessId)
Definition: gdiobj.c:348
ULONG FASTCALL FontGetObject(PTEXTOBJ plfont, ULONG cjBuffer, PVOID pvBuffer)
Definition: font.c:293
W32KAPI BOOL APIENTRY NtGdiDeleteClientObj(IN HANDLE hobj)
Definition: gdiobj.c:1419
#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:261
#define ULONG_PTR
Definition: config.h:101
VOID NTAPI GDIOBJ_vSetObjectOwner(POBJ pobj, ULONG ulNewOwner)
Definition: gdiobj.c:962
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
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:1219
NTSTATUS NTAPI MmMapViewInSessionSpace(IN PVOID Section, OUT PVOID *MappedBase, IN OUT PSIZE_T ViewSize)
Definition: section.c:2993
struct LOOKASIDE_ALIGN _PAGED_LOOKASIDE_LIST * PPAGED_LOOKASIDE_LIST
return STATUS_SUCCESS
Definition: btrfs.c:2966
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:559
void * object
Definition: jmemsys.h:48
INT NTAPI GreGetObject(IN HGDIOBJ hobj, IN INT cbCount, OUT PVOID pvBuffer)
Definition: gdiobj.c:1261
#define APIENTRY
Definition: api.h:79
VOID NTAPI GDIOBJ_vFreeObject(POBJ pobj)
Definition: gdiobj.c:593
LONGLONG QuadPart
Definition: typedefs.h:112
#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:909
Definition: ps.c:97