ReactOS  0.4.12-dev-919-gfc3b8d5
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 #define ASSERT_TRYLOCK_OBJECT_TYPE(objt) \
120  ASSERT((objt) == GDIObjType_DRVOBJ_TYPE)
121 #else
122 #define ASSERT_LOCK_ORDER(hobj)
123 #define ASSERT_SHARED_OBJECT_TYPE(objt)
124 #define ASSERT_EXCLUSIVE_OBJECT_TYPE(objt)
125 #define ASSERT_TRYLOCK_OBJECT_TYPE(objt)
126 #endif
127 
128 #if defined(_M_IX86) || defined(_M_AMD64)
129 #define InterlockedOr16 _InterlockedOr16
130 #endif
131 
132 #define GDIOBJ_POOL_TAG(type) ('00hG' + (((type) & 0x1f) << 24))
133 
134 enum
135 {
136  REF_MASK_REUSE = 0xff000000,
137  REF_INC_REUSE = 0x01000000,
138  REF_MASK_VALID = 0x00800000,
139  REF_MASK_COUNT = 0x007fffff,
140  REF_MASK_INUSE = 0x00ffffff,
141 };
142 
143 /* GLOBALS *******************************************************************/
144 
145 /* Per session handle table globals */
152 
153 static VOID NTAPI GDIOBJ_vCleanup(PVOID ObjectBody);
154 
155 static const
158 {
159  NULL, /* 00 GDIObjType_DEF_TYPE */
160  DC_vCleanup, /* 01 GDIObjType_DC_TYPE */
161  NULL, /* 02 GDIObjType_UNUSED1_TYPE */
162  NULL, /* 03 GDIObjType_UNUSED2_TYPE */
163  REGION_vCleanup, /* 04 GDIObjType_RGN_TYPE */
164  SURFACE_vCleanup, /* 05 GDIObjType_SURF_TYPE */
165  GDIOBJ_vCleanup, /* 06 GDIObjType_CLIENTOBJ_TYPE */
166  GDIOBJ_vCleanup, /* 07 GDIObjType_PATH_TYPE */
167  PALETTE_vCleanup, /* 08 GDIObjType_PAL_TYPE */
168  GDIOBJ_vCleanup, /* 09 GDIObjType_ICMLCS_TYPE */
169  GDIOBJ_vCleanup, /* 0a GDIObjType_LFONT_TYPE */
170  NULL, /* 0b GDIObjType_RFONT_TYPE, unused */
171  NULL, /* 0c GDIObjType_PFE_TYPE, unused */
172  NULL, /* 0d GDIObjType_PFT_TYPE, unused */
173  GDIOBJ_vCleanup, /* 0e GDIObjType_ICMCXF_TYPE */
174  NULL, /* 0f GDIObjType_SPRITE_TYPE, unused */
175  NULL, /* 10 GDIObjType_BRUSH_TYPE, BRUSH, PEN, EXTPEN */
176  NULL, /* 11 GDIObjType_UMPD_TYPE, unused */
177  NULL, /* 12 GDIObjType_UNUSED4_TYPE */
178  NULL, /* 13 GDIObjType_SPACE_TYPE, unused */
179  NULL, /* 14 GDIObjType_UNUSED5_TYPE */
180  NULL, /* 15 GDIObjType_META_TYPE, unused */
181  NULL, /* 16 GDIObjType_EFSTATE_TYPE, unused */
182  NULL, /* 17 GDIObjType_BMFD_TYPE, unused */
183  NULL, /* 18 GDIObjType_VTFD_TYPE, unused */
184  NULL, /* 19 GDIObjType_TTFD_TYPE, unused */
185  NULL, /* 1a GDIObjType_RC_TYPE, unused */
186  NULL, /* 1b GDIObjType_TEMP_TYPE, unused */
187  DRIVEROBJ_vCleanup,/* 1c GDIObjType_DRVOBJ_TYPE */
188  NULL, /* 1d GDIObjType_DCIOBJ_TYPE, unused */
189  NULL, /* 1e GDIObjType_SPOOL_TYPE, unused */
190  NULL, /* 1f reserved entry */
191 };
192 
193 static const
196 {
197  NULL, /* 00 GDIObjType_DEF_TYPE */
198  NULL, /* 01 GDIObjType_DC_TYPE */
199  NULL, /* 02 GDIObjType_UNUSED1_TYPE */
200  NULL, /* 03 GDIObjType_UNUSED2_TYPE */
201  NULL, /* 04 GDIObjType_RGN_TYPE */
202  NULL, /* 05 GDIObjType_SURF_TYPE */
203  NULL, /* 06 GDIObjType_CLIENTOBJ_TYPE */
204  NULL, /* 07 GDIObjType_PATH_TYPE */
205  NULL, /* 08 GDIObjType_PAL_TYPE */
206  NULL, /* 09 GDIObjType_ICMLCS_TYPE */
207  NULL, /* 0a GDIObjType_LFONT_TYPE */
208  NULL, /* 0b GDIObjType_RFONT_TYPE, unused */
209  NULL, /* 0c GDIObjType_PFE_TYPE, unused */
210  NULL, /* 0d GDIObjType_PFT_TYPE, unused */
211  NULL, /* 0e GDIObjType_ICMCXF_TYPE */
212  NULL, /* 0f GDIObjType_SPRITE_TYPE, unused */
213  BRUSH_vDeleteObject, /* 10 GDIObjType_BRUSH_TYPE, BRUSH, PEN, EXTPEN */
214  NULL, /* 11 GDIObjType_UMPD_TYPE, unused */
215  NULL, /* 12 GDIObjType_UNUSED4_TYPE */
216  NULL, /* 13 GDIObjType_SPACE_TYPE, unused */
217  NULL, /* 14 GDIObjType_UNUSED5_TYPE */
218  NULL, /* 15 GDIObjType_META_TYPE, unused */
219  NULL, /* 16 GDIObjType_EFSTATE_TYPE, unused */
220  NULL, /* 17 GDIObjType_BMFD_TYPE, unused */
221  NULL, /* 18 GDIObjType_VTFD_TYPE, unused */
222  NULL, /* 19 GDIObjType_TTFD_TYPE, unused */
223  NULL, /* 1a GDIObjType_RC_TYPE, unused */
224  NULL, /* 1b GDIObjType_TEMP_TYPE, unused */
225  NULL, /* 1c GDIObjType_DRVOBJ_TYPE */
226  NULL, /* 1d GDIObjType_DCIOBJ_TYPE, unused */
227  NULL, /* 1e GDIObjType_SPOOL_TYPE, unused */
228  NULL, /* 1f reserved entry */
229 };
230 
231 /* INTERNAL FUNCTIONS ********************************************************/
232 
233 static
234 VOID
235 NTAPI
237 {
238  /* Nothing to do */
239 }
240 
241 static
242 VOID
244 {
246  NULL,
247  NULL,
248  0,
249  cjSize,
250  GDITAG_HMGR_LOOKASIDE_START + (objt << 24),
251  0);
252 }
253 
254 INIT_FUNCTION
255 NTSTATUS
256 NTAPI
258 {
260  LARGE_INTEGER liSize;
261  PVOID pvSection;
262  SIZE_T cjViewSize = 0;
263 
264  /* Create a section for the shared handle table */
265  liSize.QuadPart = sizeof(GDI_HANDLE_TABLE); // GDI_HANDLE_COUNT * sizeof(ENTRY);
268  NULL,
269  &liSize,
271  SEC_COMMIT | 0x1,
272  NULL,
273  NULL);
274  if (!NT_SUCCESS(status))
275  {
276  DPRINT1("INITGDI: Could not allocate a GDI handle table.\n");
277  return status;
278  }
279 
280  /* Map the section in session space */
282  (PVOID*)&gpentHmgr,
283  &cjViewSize);
284  if (!NT_SUCCESS(status))
285  {
286  DPRINT1("INITGDI: Failed to map handle table section\n");
288  return status;
289  }
290 
291  /* Allocate memory for the reference counter table */
292  gpaulRefCount = EngAllocSectionMem(&pvSection,
294  GDI_HANDLE_COUNT * sizeof(ULONG),
295  'frHG');
296  if (!gpaulRefCount)
297  {
298  DPRINT1("INITGDI: Failed to allocate reference table.\n");
301  }
302 
303  gulFirstFree = 0;
305 
307 
308  /* Initialize the lookaside lists */
312  if(!gpaLookasideList)
313  return STATUS_NO_MEMORY;
314 
324 
325  return STATUS_SUCCESS;
326 }
327 
329 VOID
331 {
333  if (ppi) InterlockedIncrement((LONG*)&ppi->GDIHandleCount);
334 }
335 
337 VOID
339 {
341  if (ppi) InterlockedDecrement((LONG*)&ppi->GDIHandleCount);
342 }
343 
345 VOID
347 {
348  PEPROCESS pep;
349  PPROCESSINFO ppi;
351 
352  Status = PsLookupProcessByProcessId(ULongToHandle(ulProcessId), &pep);
355 
356  ppi = PsGetProcessWin32Process(pep);
357  if (ppi) InterlockedIncrement((LONG*)&ppi->GDIHandleCount);
359 }
360 
362 VOID
364 {
365  PEPROCESS pep;
366  PPROCESSINFO ppi;
368 
369  Status = PsLookupProcessByProcessId(ULongToHandle(ulProcessId), &pep);
372 
373  ppi = PsGetProcessWin32Process(pep);
374  if (ppi) InterlockedDecrement((LONG*)&ppi->GDIHandleCount);
376 }
377 
378 static
379 PENTRY
381 {
382  ULONG iFirst, iNext, iPrev;
383  PENTRY pentFree;
384 
385  DPRINT("Enter InterLockedPopFreeEntry\n");
386 
387  do
388  {
389  /* Get the index and sequence number of the first free entry */
391 
392  /* Check if we have a free entry */
393  if (!(iFirst & GDI_HANDLE_INDEX_MASK))
394  {
395  /* Increment FirstUnused and get the new index */
396  iFirst = InterlockedIncrement((LONG*)&gulFirstUnused) - 1;
397 
398  /* Check if we have unused entries left */
399  if (iFirst >= GDI_HANDLE_COUNT)
400  {
401  DPRINT1("No more GDI handles left!\n");
402 #if DBG_ENABLE_GDIOBJ_BACKTRACES
403  DbgDumpGdiHandleTableWithBT();
404 #endif
406  return 0;
407  }
408 
409  /* Return the old entry */
410  return &gpentHmgr[iFirst];
411  }
412 
413  /* Get a pointer to the first free entry */
414  pentFree = &gpentHmgr[iFirst & GDI_HANDLE_INDEX_MASK];
415 
416  /* Create a new value with an increased sequence number */
417  iNext = GDI_HANDLE_GET_INDEX(pentFree->einfo.hFree);
418  iNext |= (iFirst & ~GDI_HANDLE_INDEX_MASK) + 0x10000;
419 
420  /* Try to exchange the FirstFree value */
422  iNext,
423  iFirst);
424  }
425  while (iPrev != iFirst);
426 
427  /* Sanity check: is entry really free? */
428  ASSERT(((ULONG_PTR)pentFree->einfo.pobj & ~GDI_HANDLE_INDEX_MASK) == 0);
429 
430  return pentFree;
431 }
432 
433 /* Pushes an entry of the handle table to the free list,
434  The entry must not have any references left */
435 static
436 VOID
438 {
439  ULONG iToFree, iFirst, iPrev, idxToFree;
440 
441  DPRINT("Enter ENTRY_vPushFreeEntry\n");
442 
443  idxToFree = pentFree - gpentHmgr;
444  ASSERT((gpaulRefCount[idxToFree] & REF_MASK_INUSE) == 0);
445 
446  /* Initialize entry */
447  pentFree->Objt = GDIObjType_DEF_TYPE;
448  pentFree->ObjectOwner.ulObj = 0;
449  pentFree->pUser = NULL;
450 
451  /* Increase reuse counter in entry and reference counter */
453  pentFree->FullUnique += 0x0100;
454 
455  do
456  {
457  /* Get the current first free index and sequence number */
459 
460  /* Set the einfo.pobj member to the index of the first free entry */
461  pentFree->einfo.pobj = UlongToPtr(iFirst & GDI_HANDLE_INDEX_MASK);
462 
463  /* Combine new index and increased sequence number in iToFree */
464  iToFree = idxToFree | ((iFirst & ~GDI_HANDLE_INDEX_MASK) + 0x10000);
465 
466  /* Try to atomically update the first free entry */
468  iToFree,
469  iFirst);
470  }
471  while (iPrev != iFirst);
472 }
473 
474 static
475 PENTRY
477 {
478  ULONG ulIndex, cNewRefs, cOldRefs;
479  PENTRY pentry;
480 
481  /* Get the handle index and check if its too big */
483 
484  /* Get pointer to the entry */
485  pentry = &gpentHmgr[ulIndex];
486 
487  /* Get the current reference count */
488  cOldRefs = gpaulRefCount[ulIndex];
489 
490  do
491  {
492  /* Check if the slot is deleted */
493  if ((cOldRefs & REF_MASK_VALID) == 0)
494  {
495  DPRINT("GDIOBJ: Slot is not valid: 0x%lx, hobh=%p\n", cOldRefs, hobj);
496  return NULL;
497  }
498 
499  /* Check if the unique value matches */
500  if (pentry->FullUnique != (USHORT)((ULONG_PTR)hobj >> 16))
501  {
502  DPRINT("GDIOBJ: Wrong unique value. Handle: 0x%4x, entry: 0x%4x\n",
503  (USHORT)((ULONG_PTR)hobj >> 16), pentry->FullUnique);
504  return NULL;
505  }
506 
507  /* Check if the object owner is this process or public */
508  if (!(fl & GDIOBJFLAG_IGNOREPID) &&
511  {
512  DPRINT("GDIOBJ: Cannot reference foreign handle %p, pentry=%p:%lx.\n",
513  hobj, pentry, pentry->ObjectOwner.ulObj);
514  return NULL;
515  }
516 
517  /* Try to atomically increment the reference count */
518  cNewRefs = cOldRefs + 1;
520  cNewRefs,
521  cOldRefs);
522  }
523  while (cNewRefs != cOldRefs + 1);
524 
525  /* Integrity checks */
526  ASSERT((pentry->FullUnique & 0x1f) == pentry->Objt);
527  ASSERT(pentry->einfo.pobj && pentry->einfo.pobj->hHmgr == hobj);
528 
529  return pentry;
530 }
531 
532 static
533 HGDIOBJ
534 ENTRY_hInsertObject(PENTRY pentry, POBJ pobj, UCHAR objt, ULONG ulOwner)
535 {
536  ULONG ulIndex;
537 
538  /* Calculate the handle index */
539  ulIndex = pentry - gpentHmgr;
540 
541  /* Update the fields in the ENTRY */
542  pentry->einfo.pobj = pobj;
543  pentry->Objt = objt & 0x1f;
544  pentry->FullUnique = (pentry->FullUnique & 0xff00) | objt;
545  pentry->ObjectOwner.ulObj = ulOwner;
546 
547  /* Make the handle valid with 1 reference */
550 
551  /* Return the handle */
552  return (HGDIOBJ)(((ULONG_PTR)pentry->FullUnique << 16) | ulIndex);
553 }
554 
555 POBJ
556 NTAPI
558 {
559  POBJ pobj;
560 
561  if (fl & BASEFLAG_LOOKASIDE)
562  {
563  /* Allocate the object from a lookaside list */
564  pobj = ExAllocateFromPagedLookasideList(&gpaLookasideList[objt & 0x1f]);
565  }
566  else
567  {
568  /* Allocate the object from paged pool */
570  }
571 
572  if (!pobj) return NULL;
573 
574  /* Initialize the object */
575  RtlZeroMemory(pobj, cjSize);
576  pobj->hHmgr = (HGDIOBJ)((ULONG_PTR)objt << 16);
577  pobj->cExclusiveLock = 0;
578  pobj->ulShareCount = 1;
579  pobj->BaseFlags = fl & 0xffff;
580  DBG_INITLOG(&pobj->slhLog);
581  DBG_LOGEVENT(&pobj->slhLog, EVENT_ALLOCATE, 0);
582 #if DBG_ENABLE_GDIOBJ_BACKTRACES
583  DbgCaptureStackBackTace(pobj->apvBackTrace, 1, GDI_OBJECT_STACK_LEVELS);
584 #endif /* GDI_DEBUG */
585 
586  return pobj;
587 }
588 
589 VOID
590 NTAPI
592 {
593  UCHAR objt;
594 
595  DBG_CLEANUP_EVENT_LIST(&pobj->slhLog);
596 
597  /* Get the object type */
598  objt = ((ULONG_PTR)pobj->hHmgr >> 16) & 0x1f;
599 
600  /* Check if we have a delete procedure (for C++ based objects) */
601  if (apfnDelete[objt] != NULL)
602  {
603  /* Invoke the delete procedure */
604  apfnDelete[objt](pobj);
605  }
606  else
607  {
608  /* Call the cleanup procedure */
609  NT_ASSERT(apfnCleanup[objt]);
610  apfnCleanup[objt](pobj);
611 
612  /* Check if the object is allocated from a lookaside list */
613  if (pobj->BaseFlags & BASEFLAG_LOOKASIDE)
614  {
615  ExFreeToPagedLookasideList(&gpaLookasideList[objt], pobj);
616  }
617  else
618  {
619  ExFreePoolWithTag(pobj, GDIOBJ_POOL_TAG(objt));
620  }
621  }
622 }
623 
624 VOID
625 NTAPI
627 {
628  ULONG cRefs, ulIndex;
629 
630  /* Calculate the index */
632 
633  /* Check if the object has a handle */
634  if (ulIndex)
635  {
636  /* Decrement reference count */
637  if ((gpaulRefCount[ulIndex] & REF_MASK_COUNT) == 0)
638  {
639  DBG_DUMP_EVENT_LIST(&pobj->slhLog);
640  }
643  DBG_LOGEVENT(&pobj->slhLog, EVENT_DEREFERENCE, cRefs);
644 
645  /* Check if we reached 0 and handle bit is not set */
646  if ((cRefs & REF_MASK_INUSE) == 0)
647  {
648  /* Make sure it's ok to delete the object */
650 
651  /* Check if the handle was process owned */
652  if (gpentHmgr[ulIndex].ObjectOwner.ulObj != GDI_OBJ_HMGR_PUBLIC &&
654  {
655  /* Decrement the process handle count */
656  ASSERT(gpentHmgr[ulIndex].ObjectOwner.ulObj ==
659  }
660 
661  /* Push entry to the free list */
663 
664  /* Free the object */
665  GDIOBJ_vFreeObject(pobj);
666  }
667  }
668  else
669  {
670  /* Decrement the objects reference count */
671  ASSERT(pobj->ulShareCount > 0);
672  cRefs = InterlockedDecrement((LONG*)&pobj->ulShareCount);
673  DBG_LOGEVENT(&pobj->slhLog, EVENT_DEREFERENCE, cRefs);
674 
675  /* Check if we reached 0 */
676  if (cRefs == 0)
677  {
678  /* Free the object */
679  GDIOBJ_vFreeObject(pobj);
680  }
681  }
682 }
683 
684 POBJ
685 NTAPI
687  HGDIOBJ hobj,
688  UCHAR objt)
689 {
690  PENTRY pentry;
691  POBJ pobj;
692 
693  /* Check if the handle type matches */
695  if ((((ULONG_PTR)hobj >> 16) & 0x1f) != objt)
696  {
697  DPRINT("GDIOBJ: Wrong type. handle=%p, type=%x\n", hobj, objt);
698  return NULL;
699  }
700 
701  /* Reference the handle entry */
702  pentry = ENTRY_ReferenceEntryByHandle(hobj, 0);
703  if (!pentry)
704  {
705  DPRINT("GDIOBJ: Requested handle 0x%p is not valid.\n", hobj);
706  return NULL;
707  }
708 
709  /* Get the pointer to the BASEOBJECT */
710  pobj = pentry->einfo.pobj;
711 
712  /* Check if the object is exclusively locked */
713  if (pobj->cExclusiveLock != 0)
714  {
715  DPRINT1("GDIOBJ: Cannot reference object %p with exclusive lock.\n", hobj);
717  DBG_DUMP_EVENT_LIST(&pobj->slhLog);
718  return NULL;
719  }
720 
721  DBG_LOGEVENT(&pobj->slhLog, EVENT_REFERENCE, gpaulRefCount[pentry - gpentHmgr]);
722 
723  /* All is well, return the object */
724  return pobj;
725 }
726 
727 VOID
728 NTAPI
730 {
731  ULONG cRefs;
732 
733  /* Check if the object has a handle */
734  if (GDI_HANDLE_GET_INDEX(pobj->hHmgr))
735  {
736  /* Increase the handle's reference count */
740  }
741  else
742  {
743  /* Increase the object's reference count */
744  cRefs = InterlockedIncrement((LONG*)&pobj->ulShareCount);
745  }
746 
747  DBG_LOGEVENT(&pobj->slhLog, EVENT_REFERENCE, cRefs);
748 }
749 
750 PGDIOBJ
751 NTAPI
753  HGDIOBJ hobj,
754  UCHAR objt)
755 {
756  PENTRY pentry;
757  POBJ pobj;
759 
760  /* Check if the handle type matches */
762  if ((((ULONG_PTR)hobj >> 16) & 0x1f) != objt)
763  {
764  DPRINT("Wrong object type: hobj=0x%p, objt=0x%x\n", hobj, objt);
765  return NULL;
766  }
767 
768  /* Make sure lock order is correct */
769  ASSERT_LOCK_ORDER(objt);
770 
771  /* Reference the handle entry */
772  pentry = ENTRY_ReferenceEntryByHandle(hobj, 0);
773  if (!pentry)
774  {
775  DPRINT("GDIOBJ: Requested handle 0x%p is not valid.\n", hobj);
776  return NULL;
777  }
778 
779  /* Get the pointer to the BASEOBJECT */
780  pobj = pentry->einfo.pobj;
781 
782  /* Check if we already own the lock */
784  if (pobj->dwThreadId != dwThreadId)
785  {
786  /* Disable APCs and try acquiring the push lock */
789  {
790  ULONG cRefs, ulIndex;
791  /* Already owned. Clean up and leave. */
793 
794  /* Calculate the index */
796 
797  /* Decrement reference count */
800  ASSERT(cRefs & REF_MASK_VALID);
801 
802  return NULL;
803  }
804 
805  /* Set us as lock owner */
806  ASSERT(pobj->dwThreadId == 0);
807  pobj->dwThreadId = dwThreadId;
808  }
809 
810  /* Increase lock count */
811  pobj->cExclusiveLock++;
813  DBG_LOGEVENT(&pobj->slhLog, EVENT_LOCK, 0);
814 
815  /* Return the object */
816  return pobj;
817 }
818 
819 PGDIOBJ
820 NTAPI
822  HGDIOBJ hobj,
823  UCHAR objt)
824 {
825  PENTRY pentry;
826  POBJ pobj;
828 
829  /* Check if the handle type matches */
831  if ((((ULONG_PTR)hobj >> 16) & 0x1f) != objt)
832  {
833  DPRINT("Wrong object type: hobj=0x%p, objt=0x%x\n", hobj, objt);
834  return NULL;
835  }
836 
837  /* Make sure lock order is correct */
838  ASSERT_LOCK_ORDER(objt);
839 
840  /* Reference the handle entry */
841  pentry = ENTRY_ReferenceEntryByHandle(hobj, 0);
842  if (!pentry)
843  {
844  DPRINT("GDIOBJ: Requested handle 0x%p is not valid.\n", hobj);
845  return NULL;
846  }
847 
848  /* Get the pointer to the BASEOBJECT */
849  pobj = pentry->einfo.pobj;
850 
851  /* Check if we already own the lock */
853  if (pobj->dwThreadId != dwThreadId)
854  {
855  /* Disable APCs and acquire the push lock */
858 
859  /* Set us as lock owner */
860  ASSERT(pobj->dwThreadId == 0);
861  pobj->dwThreadId = dwThreadId;
862  }
863 
864  /* Increase lock count */
865  pobj->cExclusiveLock++;
867  DBG_LOGEVENT(&pobj->slhLog, EVENT_LOCK, 0);
868 
869  /* Return the object */
870  return pobj;
871 }
872 
873 VOID
874 NTAPI
876 {
877  ULONG cRefs, ulIndex;
878  ASSERT(pobj->cExclusiveLock > 0);
879 
880  /* Decrease lock count */
881  pobj->cExclusiveLock--;
883  DBG_LOGEVENT(&pobj->slhLog, EVENT_UNLOCK, 0);
884 
885  /* Check if this was the last lock */
886  if (pobj->cExclusiveLock == 0)
887  {
888  /* Reset lock owner */
889  pobj->dwThreadId = 0;
890 
891  /* Release the pushlock and reenable APCs */
894  }
895 
896  /* Calculate the index */
898 
899  /* Decrement reference count */
902  ASSERT(cRefs & REF_MASK_VALID);
903 }
904 
905 HGDIOBJ
906 NTAPI
908  POBJ pobj,
909  ULONG ulOwner)
910 {
911  PENTRY pentry;
912  UCHAR objt;
913 
914  /* Must have no handle and only one reference */
915  ASSERT(GDI_HANDLE_GET_INDEX(pobj->hHmgr) == 0);
916  ASSERT(pobj->cExclusiveLock == 0);
917  ASSERT(pobj->ulShareCount == 1);
918 
919  /* Get a free handle entry */
920  pentry = ENTRY_pentPopFreeEntry();
921  if (!pentry)
922  {
923  DPRINT1("GDIOBJ: Could not get a free entry.\n");
924  return NULL;
925  }
926 
927  /* Make the object exclusively locked */
931  pobj->cExclusiveLock = 1;
934 
935  /* Get object type from the hHmgr field */
936  objt = ((ULONG_PTR)pobj->hHmgr >> 16) & 0xff;
937  ASSERT(objt != GDIObjType_DEF_TYPE);
938 
939  /* Check if current process is requested owner */
940  if (ulOwner == GDI_OBJ_HMGR_POWNED)
941  {
942  /* Increment the process handle count */
944 
945  /* Use Process id */
947  }
948 
949  /* Insert the object into the handle table */
950  pobj->hHmgr = ENTRY_hInsertObject(pentry, pobj, objt, ulOwner);
951 
952  /* Return the handle */
953  DPRINT("GDIOBJ: Created handle: %p\n", pobj->hHmgr);
954  DBG_LOGEVENT(&pobj->slhLog, EVENT_CREATE_HANDLE, 0);
955  return pobj->hHmgr;
956 }
957 
958 VOID
959 NTAPI
961  POBJ pobj,
962  ULONG ulNewOwner)
963 {
964  PENTRY pentry;
965  ULONG ulOldOwner;
966 
967  /* This is a ugly HACK, needed to fix IntGdiSetDCOwnerEx */
968  if (GDI_HANDLE_IS_STOCKOBJ(pobj->hHmgr))
969  {
970  DPRINT("Trying to set ownership of stock object %p to %lx\n", pobj->hHmgr, ulNewOwner);
971  return;
972  }
973 
974  /* Get the handle entry */
976  pentry = &gpentHmgr[GDI_HANDLE_GET_INDEX(pobj->hHmgr)];
977 
978  /* Check if the new owner is the same as the old one */
979  ulOldOwner = pentry->ObjectOwner.ulObj;
980  if (ulOldOwner == ulNewOwner)
981  {
982  /* Nothing to do */
983  return;
984  }
985 
986  /* Is the current process requested? */
987  if (ulNewOwner == GDI_OBJ_HMGR_POWNED)
988  {
989  /* Use process id */
990  ulNewOwner = HandleToUlong(PsGetCurrentProcessId());
991  }
992 
993  // HACK
994  if (ulNewOwner == GDI_OBJ_HMGR_NONE)
995  ulNewOwner = GDI_OBJ_HMGR_PUBLIC;
996 
997  /* Was the object process owned? */
998  if ((ulOldOwner != GDI_OBJ_HMGR_PUBLIC) &&
999  (ulOldOwner != GDI_OBJ_HMGR_NONE))
1000  {
1001  /* Decrement the previous owners handle count */
1002  DecrementGdiHandleCount(ulOldOwner);
1003  }
1004 
1005  /* Is the new owner a process? */
1006  if ((ulNewOwner != GDI_OBJ_HMGR_PUBLIC) &&
1007  (ulNewOwner != GDI_OBJ_HMGR_NONE))
1008  {
1009  /* Increment the new owners handle count */
1010  IncrementGdiHandleCount(ulNewOwner);
1011  }
1012  else
1013  {
1014  /* Make sure we don't leak user mode memory */
1015  NT_ASSERT(pentry->pUser == NULL);
1016  }
1017 
1018  /* Set new owner */
1019  pentry->ObjectOwner.ulObj = ulNewOwner;
1020  DBG_LOGEVENT(&pobj->slhLog, EVENT_SET_OWNER, 0);
1021 }
1022 
1023 /* Locks 2 or 3 objects at a time */
1024 BOOL
1025 NTAPI
1027  IN ULONG ulCount,
1028  IN HGDIOBJ* ahObj,
1029  OUT PGDIOBJ* apObj,
1030  IN UCHAR objt)
1031 {
1032  UINT auiIndices[3] = {0, 1, 2};
1033  UINT i, j, tmp;
1034 
1035  ASSERT(ulCount <= 3);
1036 
1037  /* Sort the handles */
1038  for (i = 0; i < ulCount - 1; i++)
1039  {
1040  for (j = i + 1; j < ulCount; j++)
1041  {
1042  if ((ULONG_PTR)ahObj[auiIndices[i]] <
1043  (ULONG_PTR)ahObj[auiIndices[j]])
1044  {
1045  tmp = auiIndices[i];
1046  auiIndices[i] = auiIndices[j];
1047  auiIndices[j] = tmp;
1048  }
1049  }
1050  }
1051 
1052  /* Lock the objects in safe order */
1053  for (i = 0; i < ulCount; i++)
1054  {
1055  /* Skip NULL handles */
1056  if (ahObj[auiIndices[i]] == NULL)
1057  {
1058  apObj[auiIndices[i]] = NULL;
1059  continue;
1060  }
1061 
1062  /* Lock the object */
1063  apObj[auiIndices[i]] = GDIOBJ_LockObject(ahObj[auiIndices[i]], objt);
1064 
1065  /* Check for failure */
1066  if (apObj[auiIndices[i]] == NULL)
1067  {
1068  /* Cleanup */
1069  while (i--)
1070  {
1071  if (apObj[auiIndices[i]])
1072  GDIOBJ_vUnlockObject(apObj[auiIndices[i]]);
1073  }
1074  return FALSE;
1075  }
1076  }
1077 
1078  return TRUE;
1079 }
1080 
1081 PVOID
1082 NTAPI
1084 {
1086  return gpentHmgr[ulIndex].pUser;
1087 }
1088 
1089 VOID
1090 NTAPI
1092 {
1093  ULONG ulIndex;
1094 
1095  ASSERT(pobj->hHmgr);
1096 
1097  /* Get the handle index */
1099 
1100  /* Set pointer to the usermode attribute */
1101  gpentHmgr[ulIndex].pUser = pvObjAttr;
1102 }
1103 
1104 VOID
1105 NTAPI
1107 {
1108  ULONG ulIndex;
1109 
1110  /* Set the object's delete flag */
1112  DBG_LOGEVENT(&pobj->slhLog, EVENT_DELETE, 0);
1113 
1114  /* Get the handle index */
1116  if (ulIndex)
1117  {
1118  /* Reset the handle valid bit */
1120 
1121  /* Check if the object is exclusively locked */
1122  if (pobj->cExclusiveLock != 0)
1123  {
1124  /* Reset lock owner and lock count */
1125  pobj->dwThreadId = 0;
1126  pobj->cExclusiveLock = 0;
1127 
1128  /* Release the pushlock and reenable APCs */
1132  }
1133  }
1134 
1135  /* Dereference the object (will take care of deletion) */
1137 }
1138 
1139 BOOL
1140 NTAPI
1142 {
1143  PENTRY pentry;
1144 
1145  pentry = ENTRY_ReferenceEntryByHandle(hobj, 0);
1146  if (!pentry) return FALSE;
1148  return TRUE;
1149 }
1150 
1151 BOOL
1152 NTAPI
1154 {
1155  PENTRY pentry;
1156 
1157  /* Check for stock objects */
1158  if (GDI_HANDLE_IS_STOCKOBJ(hobj))
1159  {
1160  DPRINT1("GreDeleteObject: Cannot delete stock object %p.\n", hobj);
1161  return FALSE;
1162  }
1163 
1164  /* Reference the handle entry */
1165  pentry = ENTRY_ReferenceEntryByHandle(hobj, 0);
1166  if (!pentry)
1167  {
1168  DPRINT1("GreDeleteObject: Trying to delete invalid object %p\n", hobj);
1169  return FALSE;
1170  }
1171 
1172  /* Check for public owner */
1173  if (pentry->ObjectOwner.ulObj == GDI_OBJ_HMGR_PUBLIC)
1174  {
1175  DPRINT1("GreDeleteObject: Trying to delete global object %p\n", hobj);
1177  return FALSE;
1178  }
1179 
1180  /* Delete the object */
1181  GDIOBJ_vDeleteObject(pentry->einfo.pobj);
1182  return TRUE;
1183 }
1184 
1185 ULONG
1186 NTAPI
1188 {
1189  ULONG ulIndex, ulOwner;
1190 
1191  /* Get the handle index */
1192  ulIndex = GDI_HANDLE_GET_INDEX(hobj);
1193 
1194  /* Check if the handle is valid */
1195  if (ulIndex >= GDI_HANDLE_COUNT ||
1197  ((ULONG_PTR)hobj >> 16) != gpentHmgr[ulIndex].FullUnique)
1198  {
1199  DPRINT1("GreGetObjectOwner: invalid handle 0x%p.\n", hobj);
1200  return GDI_OBJ_HMGR_RESTRICTED;
1201  }
1202 
1203  /* Get the object owner */
1204  ulOwner = gpentHmgr[ulIndex].ObjectOwner.ulObj;
1205 
1206  if (ulOwner == HandleToUlong(PsGetCurrentProcessId()))
1207  return GDI_OBJ_HMGR_POWNED;
1208 
1209  if (ulOwner == GDI_OBJ_HMGR_PUBLIC)
1210  return GDI_OBJ_HMGR_PUBLIC;
1211 
1212  return GDI_OBJ_HMGR_RESTRICTED;
1213 }
1214 
1215 BOOL
1216 NTAPI
1218  HGDIOBJ hobj,
1219  ULONG ulOwner,
1220  ULONG Flags)
1221 {
1222  PENTRY pentry;
1223 
1224  /* Check for stock objects */
1225  if (GDI_HANDLE_IS_STOCKOBJ(hobj))
1226  {
1227  DPRINT("GreSetObjectOwner: Got stock object %p\n", hobj);
1228  return FALSE;
1229  }
1230 
1231  /* Reference the handle entry */
1232  pentry = ENTRY_ReferenceEntryByHandle(hobj, Flags);
1233  if (!pentry)
1234  {
1235  DPRINT("GreSetObjectOwner: Invalid handle 0x%p.\n", hobj);
1236  return FALSE;
1237  }
1238 
1239  /* Call internal function */
1240  GDIOBJ_vSetObjectOwner(pentry->einfo.pobj, ulOwner);
1241 
1242  /* Dereference the object */
1244 
1245  return TRUE;
1246 }
1247 
1248 BOOL
1249 NTAPI
1251  HGDIOBJ hobj,
1252  ULONG ulOwner)
1253 {
1254  return GreSetObjectOwnerEx(hobj, ulOwner, 0);
1255 }
1256 
1257 INT
1258 NTAPI
1260  IN HGDIOBJ hobj,
1261  IN INT cbCount,
1262  IN PVOID pvBuffer)
1263 {
1264  PVOID pvObj;
1265  UCHAR objt;
1266  INT iResult = 0;
1267 
1268  /* Verify object type */
1269  objt = ((ULONG_PTR)hobj >> 16) & 0x1f;
1270  if (objt != GDIObjType_BRUSH_TYPE &&
1271  objt != GDIObjType_SURF_TYPE &&
1272  objt != GDIObjType_LFONT_TYPE &&
1273  objt != GDIObjType_PAL_TYPE)
1274  {
1275  DPRINT1("GreGetObject: Invalid object type\n");
1276  return 0;
1277  }
1278 
1279  pvObj = GDIOBJ_ReferenceObjectByHandle(hobj, objt);
1280  if (!pvObj)
1281  {
1282  DPRINT("GreGetObject: Could not lock object\n");
1283  return 0;
1284  }
1285 
1286  switch (GDI_HANDLE_GET_TYPE(hobj))
1287  {
1290  iResult = PEN_GetObject(pvObj, cbCount, pvBuffer);
1291  break;
1292 
1294  iResult = BRUSH_GetObject(pvObj, cbCount, pvBuffer);
1295  break;
1296 
1298  iResult = BITMAP_GetObject(pvObj, cbCount, pvBuffer);
1299  break;
1300 
1302  iResult = FontGetObject(pvObj, cbCount, pvBuffer);
1303  break;
1304 
1306  iResult = PALETTE_GetObject(pvObj, cbCount, pvBuffer);
1307  break;
1308 
1309  default:
1310  DPRINT1("GDI object type of 0x%p not implemented\n", hobj);
1311  break;
1312  }
1313 
1315  return iResult;
1316 }
1317 
1318 W32KAPI
1319 INT
1320 APIENTRY
1322  IN HANDLE hobj,
1323  IN INT cjBufferSize,
1325 {
1326  UINT iResult, cjMaxSize;
1327  union
1328  {
1329  BITMAP bitmap;
1330  DIBSECTION dibsection;
1331  LOGPEN logpen;
1332  LOGBRUSH logbrush;
1333  LOGFONTW logfontw;
1334  EXTLOGFONTW extlogfontw;
1335  ENUMLOGFONTEXDVW enumlogfontexdvw;
1336  } object;
1337 
1338  /* Normalize to the largest supported object size */
1339  cjMaxSize = min((UINT)cjBufferSize, sizeof(object));
1340 
1341  /* Now do the actual call */
1342  iResult = GreGetObject(hobj, cjMaxSize, lpBuffer ? &object : NULL);
1343 
1344  /* Check if we have a buffer and data */
1345  if ((lpBuffer != NULL) && (iResult != 0))
1346  {
1347  /* Enter SEH for buffer transfer */
1348  _SEH2_TRY
1349  {
1350  /* Probe the buffer and copy it */
1351  cjMaxSize = min(cjMaxSize, iResult);
1352  ProbeForWrite(lpBuffer, cjMaxSize, sizeof(WORD));
1353  RtlCopyMemory(lpBuffer, &object, cjMaxSize);
1354  }
1356  {
1357  /* Clear the return value.
1358  * Do *NOT* set last error here! */
1359  iResult = 0;
1360  }
1361  _SEH2_END;
1362  }
1363 
1364  /* Return the count */
1365  return iResult;
1366 }
1367 
1368 W32KAPI
1369 HANDLE
1370 APIENTRY
1372  IN ULONG ulType)
1373 {
1374  POBJ pObject;
1375  HANDLE handle;
1376 
1377  /* Check if ulType is valid */
1381  {
1382  DPRINT1("NtGdiCreateClientObj: Invalid object type 0x%lx.\n", ulType);
1383  return NULL;
1384  }
1385 
1386  /* Allocate a new object */
1388  sizeof(CLIENTOBJ),
1390  if (!pObject)
1391  {
1392  DPRINT1("NtGdiCreateClientObj: Could not allocate a clientobj.\n");
1393  return NULL;
1394  }
1395 
1396  /* Set the real object type */
1398 
1399  /* Create a handle */
1401  if (!handle)
1402  {
1403  DPRINT1("NtGdiCreateClientObj: Could not create a handle.\n");
1404  GDIOBJ_vFreeObject(pObject);
1405  return NULL;
1406  }
1407 
1408  /* Unlock it */
1409  GDIOBJ_vUnlockObject(pObject);
1410 
1411  return handle;
1412 }
1413 
1414 W32KAPI
1415 BOOL
1416 APIENTRY
1418  IN HANDLE hobj)
1419 {
1420  /* We first need to get the real type from the handle */
1422 
1423  /* Check if it's really a CLIENTOBJ */
1425  {
1426  /* FIXME: SetLastError? */
1427  return FALSE;
1428  }
1429 
1430  return GreDeleteObject(hobj);
1431 }
1432 
1433 
1434 
1436 
1437 PGDIOBJ NTAPI
1438 GDIOBJ_ShareLockObj(HGDIOBJ hObj, DWORD ExpectedType)
1439 {
1440  if (ExpectedType == GDI_OBJECT_TYPE_DONTCARE)
1441  ExpectedType = GDI_HANDLE_GET_TYPE(hObj);
1442  return GDIOBJ_ReferenceObjectByHandle(hObj, (ExpectedType >> 16) & 0x1f);
1443 }
1444 
1445 // This function is not safe to use with concurrent deleting attempts
1446 // That shouldn't be a problem, since we don't have any processes yet,
1447 // that could delete the handle
1448 BOOL
1449 NTAPI
1451 {
1452  PENTRY pentry;
1453  POBJ pobj;
1454 
1455  /* Reference the handle entry */
1456  pentry = ENTRY_ReferenceEntryByHandle(*phObj, 0);
1457  if (!pentry)
1458  {
1459  DPRINT1("GDIOBJ: Requested handle 0x%p is not valid.\n", *phObj);
1460  return FALSE;
1461  }
1462 
1463  /* Update the entry */
1464  pentry->FullUnique |= GDI_ENTRY_STOCK_MASK;
1465  pentry->ObjectOwner.ulObj = 0;
1466 
1467  /* Get the pointer to the BASEOBJECT */
1468  pobj = pentry->einfo.pobj;
1469 
1470  /* Calculate the new handle */
1471  pobj->hHmgr = (HGDIOBJ)((ULONG_PTR)pobj->hHmgr | GDI_HANDLE_STOCK_MASK);
1472 
1473  /* Return the new handle */
1474  *phObj = pobj->hHmgr;
1475 
1476  /* Dereference the handle */
1478 
1479  return TRUE;
1480 }
1481 
1482 POBJ NTAPI
1484 {
1485  POBJ pobj;
1486  FLONG fl = 0;
1487  UCHAR objt = (ObjectType >> 16) & 0xFF;
1488 
1489  if ((objt == GDIObjType_DC_TYPE && cjSize == sizeof(DC)) ||
1490  (objt == GDIObjType_PAL_TYPE && cjSize == sizeof(PALETTE)) ||
1491  (objt == GDIObjType_RGN_TYPE && cjSize == sizeof(REGION)) ||
1492  (objt == GDIObjType_SURF_TYPE && cjSize == sizeof(SURFACE)) ||
1493  (objt == GDIObjType_PATH_TYPE && cjSize == sizeof(PATH)))
1494  {
1496  }
1497 
1498  pobj = GDIOBJ_AllocateObject(objt, cjSize, fl);
1499  if (!pobj)
1500  {
1501  return NULL;
1502  }
1503 
1505  {
1506  GDIOBJ_vFreeObject(pobj);
1507  return NULL;
1508  }
1509  return pobj;
1510 }
1511 
1512 PVOID NTAPI
1514 {
1515  PVOID pvMappedView = NULL;
1516  NTSTATUS Status;
1517  LARGE_INTEGER liOffset;
1518  SIZE_T cjViewSize = sizeof(GDI_HANDLE_TABLE);
1519 
1520  liOffset.QuadPart = 0;
1521 
1523  ASSERT(pProcess != NULL);
1524 
1526  pProcess,
1527  &pvMappedView,
1528  0,
1529  0,
1530  &liOffset,
1531  &cjViewSize,
1532  ViewUnmap,
1533  SEC_NO_CHANGE,
1534  PAGE_READONLY);
1535 
1536  if (!NT_SUCCESS(Status))
1537  return NULL;
1538 
1539  return pvMappedView;
1540 }
1541 
1542 BOOL NTAPI
1544 {
1545  PENTRY pentry;
1546  ULONG ulIndex;
1547  DWORD dwProcessId;
1548  PPROCESSINFO ppi;
1549 
1550  DPRINT("CleanupForProcess prochandle %p Pid %p\n",
1551  Process, Process->UniqueProcessId);
1552 
1554 
1555  /* Get the current process Id */
1556  dwProcessId = PtrToUlong(PsGetCurrentProcessId());
1557 
1558  /* Loop all handles in the handle table */
1560  {
1561  pentry = &gpentHmgr[ulIndex];
1562 
1563  /* Check if the object is owned by the process */
1564  if (pentry->ObjectOwner.ulObj == dwProcessId)
1565  {
1566  ASSERT(pentry->einfo.pobj->cExclusiveLock == 0);
1567 
1568  /* Reference the object and delete it */
1570  GDIOBJ_vDeleteObject(pentry->einfo.pobj);
1571  }
1572  }
1573 
1574 #if DBG
1576 #endif
1577 
1579  DPRINT("Completed cleanup for process %p\n", Process->UniqueProcessId);
1580  if (ppi->GDIHandleCount != 0)
1581  {
1582  DPRINT1("Leaking %d handles!\n", ppi->GDIHandleCount);
1583  ASSERT(FALSE);
1584  }
1585 
1586  /* Loop all handles in the handle table */
1588  {
1589  pentry = &gpentHmgr[ulIndex];
1590 
1591  /* Check if the object is owned by the process */
1592  if (pentry->ObjectOwner.ulObj == dwProcessId)
1593  {
1594  DPRINT1("Leaking object. Index=%lx, type=0x%x, refcount=%lx\n",
1595  ulIndex, pentry->Objt, gpaulRefCount[ulIndex]);
1596  DBG_DUMP_EVENT_LIST(&pentry->einfo.pobj->slhLog);
1597  //DBG_CLEANUP_EVENT_LIST(&pentry->einfo.pobj->slhLog);
1598  ASSERT(FALSE);
1599  }
1600  }
1601 
1602  return TRUE;
1603 }
1604 
1606 PGDI_POOL
1608 {
1609  PPROCESSINFO ppi;
1610 
1612  NT_ASSERT(ppi != NULL);
1613 
1614  return ppi->pPoolBrushAttr;
1615 }
1616 
1617 /* 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:821
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:1250
#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:1153
#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:247
struct _PALETTE PALETTE
BOOL NTAPI GreIsHandleValid(HGDIOBJ hobj)
Definition: gdiobj.c:1141
ULONG ulShareCount
Definition: gdiobj.h:42
volatile ULONG gulFirstUnused
Definition: gdiobj.c:150
#define GDI_OBJ_HMGR_RESTRICTED
Definition: ntgdihdl.h:119
POBJ NTAPI GDIOBJ_ReferenceObjectByHandle(HGDIOBJ hobj, UCHAR objt)
Definition: gdiobj.c:686
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:257
#define DBG_UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:325
UCHAR Objt
Definition: ntgdihdl.h:245
static PPAGED_LOOKASIDE_LIST gpaLookasideList
Definition: gdiobj.c:151
PVOID NTAPI GDI_MapHandleTable(PEPROCESS pProcess)
Definition: gdiobj.c:1513
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:125
#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:243
#define InterlockedCompareExchange
Definition: interlocked.h:104
struct _BASEOBJECT * pobj
Definition: ntgdihdl.h:230
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:626
#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:1187
volatile ULONG gulFirstFree
Definition: gdiobj.c:149
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:338
#define GDI_HANDLE_BASETYPE_MASK
Definition: gdi.h:18
INT FASTCALL PALETTE_GetObject(PPALETTE ppal, INT cbCount, LPLOGBRUSH lpBuffer)
Definition: palette.c:244
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:132
static PENTRY ENTRY_ReferenceEntryByHandle(HGDIOBJ hobj, FLONG fl)
Definition: gdiobj.c:476
W32KAPI INT APIENTRY NtGdiExtGetObjectW(IN HANDLE hobj, IN INT cjBufferSize, OUT LPVOID lpBuffer)
Definition: gdiobj.c:1321
#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:1450
Definition: text.h:59
unsigned int BOOL
Definition: ntddk_ex.h:94
static VOID ENTRY_vPushFreeEntry(PENTRY pentFree)
Definition: gdiobj.c:437
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:1438
FORCEINLINE ULONG InterlockedReadUlong(_In_ _Interlocked_operand_ ULONG volatile *Source)
Definition: gdiobj.c:55
PVOID NTAPI GDIOBJ_pvGetObjectAttr(POBJ pobj)
Definition: gdiobj.c:1083
PULONG gpaulRefCount
Definition: gdiobj.c:148
#define __analysis_assume(expr)
Definition: sal.h:1111
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:1435
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:4496
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:1026
#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:1543
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:1106
static const GDIOBJDELETEPROC apfnDelete[]
Definition: gdiobj.c:195
W32KAPI HANDLE APIENTRY NtGdiCreateClientObj(IN ULONG ulType)
Definition: gdiobj.c:1371
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define ASSERT_SHARED_OBJECT_TYPE(objt)
Definition: gdiobj.c:123
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:4969
#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:380
unsigned long DWORD
Definition: ntddk_ex.h:95
PGDI_POOL GetBrushAttrPool(VOID)
HACK!
Definition: gdiobj.c:1607
FORCEINLINE VOID IncrementCurrentProcessGdiHandleCount(void)
Definition: gdiobj.c:330
static VOID NTAPI GDIOBJ_vCleanup(PVOID ObjectBody)
Definition: gdiobj.c:236
ULONG ulObj
Definition: ntgdihdl.h:241
VOID NTAPI GDIOBJ_vSetObjectAttr(POBJ pobj, PVOID pvObjAttr)
Definition: gdiobj.c:1091
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:875
#define ASSERT_LOCK_ORDER(hobj)
Definition: gdiobj.c:122
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:124
#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:2412
#define KeEnterCriticalRegion()
Definition: ke_x.h:83
static HGDIOBJ ENTRY_hInsertObject(PENTRY pentry, POBJ pobj, UCHAR objt, ULONG ulOwner)
Definition: gdiobj.c:534
#define InterlockedOr
Definition: interlocked.h:224
#define GDI_OBJ_HMGR_POWNED
Definition: ntgdihdl.h:117
PENTRY gpentHmgr
Definition: gdiobj.c:147
struct _REGION REGION
HGDIOBJ hFree
Definition: ntgdihdl.h:231
#define GDI_OBJECT_TYPE_DONTCARE
Definition: gdi.h:64
static PVOID gpvGdiHdlTblSection
Definition: gdiobj.c:146
#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:233
#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:244
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:752
POBJ NTAPI GDIOBJ_AllocObjWithHandle(ULONG ObjectType, ULONG cjSize)
Definition: gdiobj.c:1483
#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:729
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:363
#define OUT
Definition: typedefs.h:39
FORCEINLINE VOID IncrementGdiHandleCount(ULONG ulProcessId)
Definition: gdiobj.c:346
ULONG FASTCALL FontGetObject(PTEXTOBJ plfont, ULONG cjBuffer, PVOID pvBuffer)
Definition: font.c:293
W32KAPI BOOL APIENTRY NtGdiDeleteClientObj(IN HANDLE hobj)
Definition: gdiobj.c:1417
#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:960
static HBITMAP bitmap
Definition: clipboard.c:1344
_In_ UINT _In_ UINT _In_ PNDIS_PACKET Source
Definition: ndis.h:3149
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:6
union _ENTRY::_OBJECTOWNER ObjectOwner
Definition: ntgdihdl.h:226
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1099
static const GDICLEANUPPROC apfnCleanup[]
Definition: gdiobj.c:157
BOOL NTAPI GreSetObjectOwnerEx(HGDIOBJ hobj, ULONG ulOwner, ULONG Flags)
Definition: gdiobj.c:1217
NTSTATUS NTAPI MmMapViewInSessionSpace(IN PVOID Section, OUT PVOID *MappedBase, IN OUT PSIZE_T ViewSize)
Definition: section.c:2991
struct LOOKASIDE_ALIGN _PAGED_LOOKASIDE_LIST * PPAGED_LOOKASIDE_LIST
return STATUS_SUCCESS
Definition: btrfs.c:2725
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:349
POBJ NTAPI GDIOBJ_AllocateObject(UCHAR objt, ULONG cjSize, FLONG fl)
Definition: gdiobj.c:557
void * object
Definition: jmemsys.h:48
#define APIENTRY
Definition: api.h:79
VOID NTAPI GDIOBJ_vFreeObject(POBJ pobj)
Definition: gdiobj.c:591
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
INT NTAPI GreGetObject(IN HGDIOBJ hobj, IN INT cbCount, IN PVOID pvBuffer)
Definition: gdiobj.c:1259
#define NT_ASSERT
Definition: rtlfuncs.h:3312
HGDIOBJ NTAPI GDIOBJ_hInsertObject(POBJ pobj, ULONG ulOwner)
Definition: gdiobj.c:907
Definition: ps.c:97