ReactOS 0.4.16-dev-1946-g52006dd
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
57{
58 return *Source;
59}
60
62void
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
78void
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
94VOID
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
136enum
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
155static VOID NTAPI GDIOBJ_vCleanup(PVOID ObjectBody);
156
157static 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
195static 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
235static
236VOID
237NTAPI
239{
240 /* Nothing to do */
241}
242
243static
244VOID
246{
248 NULL,
249 NULL,
250 0,
251 cjSize,
252 GDITAG_HMGR_LOOKASIDE_START + (objt << 24),
253 0);
254}
255
256CODE_SEG("INIT")
258NTAPI
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 */
315 return STATUS_NO_MEMORY;
316
326
327 return STATUS_SUCCESS;
328}
329
331VOID
333{
335 if (ppi) InterlockedIncrement((LONG*)&ppi->GDIHandleCount);
336}
337
339VOID
341{
343 if (ppi) InterlockedDecrement((LONG*)&ppi->GDIHandleCount);
344}
345
346static inline
347VOID
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
363static inline
364VOID
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
380static
381PENTRY
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 */
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 */
437static
438VOID
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
476static
477PENTRY
479{
480 ULONG ulIndex, cNewRefs, cOldRefs;
481 PENTRY pentry;
483
484 /* HACK: This may be a hack but it fixes CORE-5601.
485 * Allow a window that is moving or resizing to have access to all of its child
486 * windows dc's even if the dc belongs to another process i.e. 3D Screensaver */
487 if (pti && pti->TIF_flags & TIF_MOVESIZETRACKING)
489
490 /* Get the handle index and check if its too big */
491 ulIndex = GDI_HANDLE_GET_INDEX(hobj);
492
493 /* Get pointer to the entry */
494 pentry = &gpentHmgr[ulIndex];
495
496 /* Get the current reference count */
497 cOldRefs = gpaulRefCount[ulIndex];
498
499 do
500 {
501 /* Check if the slot is deleted */
502 if ((cOldRefs & REF_MASK_VALID) == 0)
503 {
504 DPRINT("GDIOBJ: Slot is not valid: 0x%lx, hobh=%p\n", cOldRefs, hobj);
505 return NULL;
506 }
507
508 /* Check if the unique value matches */
509 if (pentry->FullUnique != (USHORT)((ULONG_PTR)hobj >> 16))
510 {
511 DPRINT("GDIOBJ: Wrong unique value. Handle: 0x%4x, entry: 0x%4x\n",
512 (USHORT)((ULONG_PTR)hobj >> 16), pentry->FullUnique);
513 return NULL;
514 }
515
516 /* Check if the object owner is this process or public */
517 if (!(fl & GDIOBJFLAG_IGNOREPID) &&
520 {
521 DPRINT("GDIOBJ: Cannot reference foreign handle %p, pentry=%p:%lx.\n",
522 hobj, pentry, pentry->ObjectOwner.ulObj);
523 return NULL;
524 }
525
526 /* Try to atomically increment the reference count */
527 cNewRefs = cOldRefs + 1;
528 cOldRefs = InterlockedCompareExchange((PLONG)&gpaulRefCount[ulIndex],
529 cNewRefs,
530 cOldRefs);
531 }
532 while (cNewRefs != cOldRefs + 1);
533
534 /* Integrity checks */
535 ASSERT((pentry->FullUnique & 0x1f) == pentry->Objt);
536 ASSERT(pentry->einfo.pobj != NULL);
537
538 /* Check if lower 32 bits match, the upper 32 bits are ignored */
539 ASSERT(pentry->einfo.pobj->hHmgr == UlongToPtr(PtrToUlong(hobj)));
540
541 return pentry;
542}
543
544static
546ENTRY_hInsertObject(PENTRY pentry, POBJ pobj, UCHAR objt, ULONG ulOwner)
547{
548 ULONG ulIndex;
549
550 /* Calculate the handle index */
551 ulIndex = pentry - gpentHmgr;
552
553 /* Update the fields in the ENTRY */
554 pentry->einfo.pobj = pobj;
555 pentry->Objt = objt & 0x1f;
556 pentry->FullUnique = (pentry->FullUnique & 0xff00) | objt;
557 pentry->ObjectOwner.ulObj = ulOwner;
558
559 /* Make the handle valid with 1 reference */
560 ASSERT((gpaulRefCount[ulIndex] & REF_MASK_INUSE) == 0);
562
563 /* Return the handle */
564 return (HGDIOBJ)(((ULONG_PTR)pentry->FullUnique << 16) | ulIndex);
565}
566
567POBJ
568NTAPI
570{
571 POBJ pobj;
572
574 {
575 /* Allocate the object from a lookaside list */
576 pobj = ExAllocateFromPagedLookasideList(&gpaLookasideList[objt & 0x1f]);
577 }
578 else
579 {
580 /* Allocate the object from paged pool */
582 }
583
584 if (!pobj) return NULL;
585
586 /* Initialize the object */
587 RtlZeroMemory(pobj, cjSize);
588 pobj->hHmgr = (HGDIOBJ)((ULONG_PTR)objt << 16);
589 pobj->cExclusiveLock = 0;
590 pobj->ulShareCount = 1;
591 pobj->BaseFlags = fl & 0xffff;
592 DBG_INITLOG(&pobj->slhLog);
593 DBG_LOGEVENT(&pobj->slhLog, EVENT_ALLOCATE, 0);
594#if DBG_ENABLE_GDIOBJ_BACKTRACES
595 DbgCaptureStackBackTace(pobj->apvBackTrace, 1, GDI_OBJECT_STACK_LEVELS);
596#endif /* GDI_DEBUG */
597
598 return pobj;
599}
600
601VOID
602NTAPI
604{
605 UCHAR objt;
606
607 DBG_CLEANUP_EVENT_LIST(&pobj->slhLog);
608
609 /* Get the object type */
610 objt = ((ULONG_PTR)pobj->hHmgr >> 16) & 0x1f;
611
612 /* Check if we have a delete procedure (for C++ based objects) */
613 if (apfnDelete[objt] != NULL)
614 {
615 /* Invoke the delete procedure */
616 apfnDelete[objt](pobj);
617 }
618 else
619 {
620 /* Call the cleanup procedure */
621 NT_ASSERT(apfnCleanup[objt]);
622 apfnCleanup[objt](pobj);
623
624 /* Check if the object is allocated from a lookaside list */
625 if (pobj->BaseFlags & BASEFLAG_LOOKASIDE)
626 {
627 ExFreeToPagedLookasideList(&gpaLookasideList[objt], pobj);
628 }
629 else
630 {
632 }
633 }
634}
635
636VOID
637NTAPI
639{
640 ULONG cRefs, ulIndex;
641
642 /* Calculate the index */
643 ulIndex = GDI_HANDLE_GET_INDEX(pobj->hHmgr);
644
645 /* Check if the object has a handle */
646 if (ulIndex)
647 {
648 /* Decrement reference count */
649 if ((gpaulRefCount[ulIndex] & REF_MASK_COUNT) == 0)
650 {
651 DBG_DUMP_EVENT_LIST(&pobj->slhLog);
652 }
653 ASSERT((gpaulRefCount[ulIndex] & REF_MASK_COUNT) > 0);
654 cRefs = InterlockedDecrement((LONG*)&gpaulRefCount[ulIndex]);
655 DBG_LOGEVENT(&pobj->slhLog, EVENT_DEREFERENCE, cRefs);
656
657 /* Check if we reached 0 and handle bit is not set */
658 if ((cRefs & REF_MASK_INUSE) == 0)
659 {
660 /* Make sure it's ok to delete the object */
662
663 /* Check if the handle was process owned */
664 if (gpentHmgr[ulIndex].ObjectOwner.ulObj != GDI_OBJ_HMGR_PUBLIC &&
666 {
667 /* Decrement the process handle count */
668 ASSERT(gpentHmgr[ulIndex].ObjectOwner.ulObj ==
671 }
672
673 /* Push entry to the free list */
675
676 /* Free the object */
677 GDIOBJ_vFreeObject(pobj);
678 }
679 }
680 else
681 {
682 /* Decrement the objects reference count */
683 ASSERT(pobj->ulShareCount > 0);
684 cRefs = InterlockedDecrement((LONG*)&pobj->ulShareCount);
685 DBG_LOGEVENT(&pobj->slhLog, EVENT_DEREFERENCE, cRefs);
686
687 /* Check if we reached 0 */
688 if (cRefs == 0)
689 {
690 /* Free the object */
691 GDIOBJ_vFreeObject(pobj);
692 }
693 }
694}
695
696POBJ
697NTAPI
699 HGDIOBJ hobj,
700 UCHAR objt)
701{
702 PENTRY pentry;
703 POBJ pobj;
704
705 /* Check if the handle type matches */
707 if ((((ULONG_PTR)hobj >> 16) & 0x1f) != objt)
708 {
709 DPRINT("GDIOBJ: Wrong type. handle=%p, type=%x\n", hobj, objt);
710 return NULL;
711 }
712
713 /* Reference the handle entry */
714 pentry = ENTRY_ReferenceEntryByHandle(hobj, 0);
715 if (!pentry)
716 {
717 DPRINT("GDIOBJ: Requested handle 0x%p is not valid.\n", hobj);
718 return NULL;
719 }
720
721 /* Get the pointer to the BASEOBJECT */
722 pobj = pentry->einfo.pobj;
723
724 /* Check if the object is exclusively locked */
725 if (pobj->cExclusiveLock != 0)
726 {
727 DPRINT1("GDIOBJ: Cannot reference object %p with exclusive lock.\n", hobj);
729 DBG_DUMP_EVENT_LIST(&pobj->slhLog);
730 return NULL;
731 }
732
733 DBG_LOGEVENT(&pobj->slhLog, EVENT_REFERENCE, gpaulRefCount[pentry - gpentHmgr]);
734
735 /* All is well, return the object */
736 return pobj;
737}
738
739VOID
740NTAPI
742{
743 ULONG cRefs;
744
745 /* Check if the object has a handle */
746 if (GDI_HANDLE_GET_INDEX(pobj->hHmgr))
747 {
748 /* Increase the handle's reference count */
749 ULONG ulIndex = GDI_HANDLE_GET_INDEX(pobj->hHmgr);
750 ASSERT((gpaulRefCount[ulIndex] & REF_MASK_COUNT) > 0);
751 cRefs = InterlockedIncrement((LONG*)&gpaulRefCount[ulIndex]);
752 }
753 else
754 {
755 /* Increase the object's reference count */
756 cRefs = InterlockedIncrement((LONG*)&pobj->ulShareCount);
757 }
758
759 DBG_LOGEVENT(&pobj->slhLog, EVENT_REFERENCE, cRefs);
760}
761
763NTAPI
765 HGDIOBJ hobj,
766 UCHAR objt)
767{
768 PENTRY pentry;
769 POBJ pobj;
771
772 /* Check if the handle type matches */
774 if ((((ULONG_PTR)hobj >> 16) & 0x1f) != objt)
775 {
776 DPRINT("Wrong object type: hobj=0x%p, objt=0x%x\n", hobj, objt);
777 return NULL;
778 }
779
780 /* Make sure lock order is correct */
781 ASSERT_LOCK_ORDER(objt);
782
783 /* Reference the handle entry */
784 pentry = ENTRY_ReferenceEntryByHandle(hobj, 0);
785 if (!pentry)
786 {
787 DPRINT("GDIOBJ: Requested handle 0x%p is not valid.\n", hobj);
788 return NULL;
789 }
790
791 /* Get the pointer to the BASEOBJECT */
792 pobj = pentry->einfo.pobj;
793
794 /* Check if we already own the lock */
796 if (pobj->dwThreadId != dwThreadId)
797 {
798 /* Disable APCs and try acquiring the push lock */
801 {
802 ULONG cRefs, ulIndex;
803 /* Already owned. Clean up and leave. */
805
806 /* Calculate the index */
807 ulIndex = GDI_HANDLE_GET_INDEX(pobj->hHmgr);
808
809 /* Decrement reference count */
810 ASSERT((gpaulRefCount[ulIndex] & REF_MASK_COUNT) > 0);
811 cRefs = InterlockedDecrement((LONG*)&gpaulRefCount[ulIndex]);
812 ASSERT(cRefs & REF_MASK_VALID);
813
814 return NULL;
815 }
816
817 /* Set us as lock owner */
818 ASSERT(pobj->dwThreadId == 0);
819 pobj->dwThreadId = dwThreadId;
820 }
821
822 /* Increase lock count */
823 pobj->cExclusiveLock++;
825 DBG_LOGEVENT(&pobj->slhLog, EVENT_LOCK, 0);
826
827 /* Return the object */
828 return pobj;
829}
830
832NTAPI
834 HGDIOBJ hobj,
835 UCHAR objt)
836{
837 PENTRY pentry;
838 POBJ pobj;
840
841 /* Check if the handle type matches */
843 if ((((ULONG_PTR)hobj >> 16) & 0x1f) != objt)
844 {
845 DPRINT("Wrong object type: hobj=0x%p, objt=0x%x\n", hobj, objt);
846 return NULL;
847 }
848
849 /* Make sure lock order is correct */
850 ASSERT_LOCK_ORDER(objt);
851
852 /* Reference the handle entry */
853 pentry = ENTRY_ReferenceEntryByHandle(hobj, 0);
854 if (!pentry)
855 {
856 DPRINT("GDIOBJ: Requested handle 0x%p is not valid.\n", hobj);
857 return NULL;
858 }
859
860 /* Get the pointer to the BASEOBJECT */
861 pobj = pentry->einfo.pobj;
862
863 /* Check if we already own the lock */
865 if (pobj->dwThreadId != dwThreadId)
866 {
867 /* Disable APCs and acquire the push lock */
870
871 /* Set us as lock owner */
872 ASSERT(pobj->dwThreadId == 0);
873 pobj->dwThreadId = dwThreadId;
874 }
875
876 /* Increase lock count */
877 pobj->cExclusiveLock++;
879 DBG_LOGEVENT(&pobj->slhLog, EVENT_LOCK, 0);
880
881 /* Return the object */
882 return pobj;
883}
884
885VOID
886NTAPI
888{
889 ULONG cRefs, ulIndex;
890 ASSERT(pobj->cExclusiveLock > 0);
891
892 /* Decrease lock count */
893 pobj->cExclusiveLock--;
895 DBG_LOGEVENT(&pobj->slhLog, EVENT_UNLOCK, 0);
896
897 /* Check if this was the last lock */
898 if (pobj->cExclusiveLock == 0)
899 {
900 /* Reset lock owner */
901 pobj->dwThreadId = 0;
902
903 /* Release the pushlock and reenable APCs */
906 }
907
908 /* Calculate the index */
909 ulIndex = GDI_HANDLE_GET_INDEX(pobj->hHmgr);
910
911 /* Decrement reference count */
912 ASSERT((gpaulRefCount[ulIndex] & REF_MASK_COUNT) > 0);
913 cRefs = InterlockedDecrement((LONG*)&gpaulRefCount[ulIndex]);
914 ASSERT(cRefs & REF_MASK_VALID);
915}
916
918NTAPI
920 POBJ pobj,
921 ULONG ulOwner)
922{
923 PENTRY pentry;
924 UCHAR objt;
925
926 /* Must have no handle and only one reference */
927 ASSERT(GDI_HANDLE_GET_INDEX(pobj->hHmgr) == 0);
928 ASSERT(pobj->cExclusiveLock == 0);
929 ASSERT(pobj->ulShareCount == 1);
930
931 /* Get a free handle entry */
932 pentry = ENTRY_pentPopFreeEntry();
933 if (!pentry)
934 {
935 DPRINT1("GDIOBJ: Could not get a free entry.\n");
936 return NULL;
937 }
938
939 /* Make the object exclusively locked */
943 pobj->cExclusiveLock = 1;
946
947 /* Get object type from the hHmgr field */
948 objt = ((ULONG_PTR)pobj->hHmgr >> 16) & 0xff;
950
951 /* Check if current process is requested owner */
952 if (ulOwner == GDI_OBJ_HMGR_POWNED)
953 {
954 /* Increment the process handle count */
956
957 /* Use Process id */
959 }
960
961 /* Insert the object into the handle table */
962 pobj->hHmgr = ENTRY_hInsertObject(pentry, pobj, objt, ulOwner);
963
964 /* Return the handle */
965 DPRINT("GDIOBJ: Created handle: %p\n", pobj->hHmgr);
966 DBG_LOGEVENT(&pobj->slhLog, EVENT_CREATE_HANDLE, 0);
967 return pobj->hHmgr;
968}
969
970VOID
971NTAPI
973 POBJ pobj,
974 ULONG ulNewOwner)
975{
976 PENTRY pentry;
977 ULONG ulOldOwner;
978
979 /* This is a ugly HACK, needed to fix IntGdiSetDCOwnerEx */
980 if (GDI_HANDLE_IS_STOCKOBJ(pobj->hHmgr))
981 {
982 DPRINT("Trying to set ownership of stock object %p to %lx\n", pobj->hHmgr, ulNewOwner);
983 return;
984 }
985
986 /* Get the handle entry */
988 pentry = &gpentHmgr[GDI_HANDLE_GET_INDEX(pobj->hHmgr)];
989
990 /* Check if the new owner is the same as the old one */
991 ulOldOwner = pentry->ObjectOwner.ulObj;
992 if (ulOldOwner == ulNewOwner)
993 {
994 /* Nothing to do */
995 return;
996 }
997
998 /* Is the current process requested? */
999 if (ulNewOwner == GDI_OBJ_HMGR_POWNED)
1000 {
1001 /* Use process id */
1002 ulNewOwner = HandleToUlong(PsGetCurrentProcessId());
1003 }
1004
1005 // HACK
1006 if (ulNewOwner == GDI_OBJ_HMGR_NONE)
1007 ulNewOwner = GDI_OBJ_HMGR_PUBLIC;
1008
1009 /* Was the object process owned? */
1010 if ((ulOldOwner != GDI_OBJ_HMGR_PUBLIC) &&
1011 (ulOldOwner != GDI_OBJ_HMGR_NONE))
1012 {
1013 /* Decrement the previous owners handle count */
1014 DecrementGdiHandleCount(ulOldOwner);
1015 }
1016
1017 /* Is the new owner a process? */
1018 if ((ulNewOwner != GDI_OBJ_HMGR_PUBLIC) &&
1019 (ulNewOwner != GDI_OBJ_HMGR_NONE))
1020 {
1021 /* Increment the new owners handle count */
1022 IncrementGdiHandleCount(ulNewOwner);
1023 }
1024 else
1025 {
1026 /* Make sure we don't leak user mode memory */
1027 NT_ASSERT(pentry->pUser == NULL);
1028 }
1029
1030 /* Set new owner */
1031 pentry->ObjectOwner.ulObj = ulNewOwner;
1032 DBG_LOGEVENT(&pobj->slhLog, EVENT_SET_OWNER, 0);
1033}
1034
1035/* Locks 2 or 3 objects at a time */
1036BOOL
1037NTAPI
1039 IN ULONG ulCount,
1040 IN HGDIOBJ* ahObj,
1041 OUT PGDIOBJ* apObj,
1042 IN UCHAR objt)
1043{
1044 UINT auiIndices[3] = {0, 1, 2};
1045 UINT i, j, tmp;
1046
1047 ASSERT(ulCount <= 3);
1048
1049 /* Sort the handles */
1050 for (i = 0; i < ulCount - 1; i++)
1051 {
1052 for (j = i + 1; j < ulCount; j++)
1053 {
1054 if ((ULONG_PTR)ahObj[auiIndices[i]] <
1055 (ULONG_PTR)ahObj[auiIndices[j]])
1056 {
1057 tmp = auiIndices[i];
1058 auiIndices[i] = auiIndices[j];
1059 auiIndices[j] = tmp;
1060 }
1061 }
1062 }
1063
1064 /* Lock the objects in safe order */
1065 for (i = 0; i < ulCount; i++)
1066 {
1067 /* Skip NULL handles */
1068 if (ahObj[auiIndices[i]] == NULL)
1069 {
1070 apObj[auiIndices[i]] = NULL;
1071 continue;
1072 }
1073
1074 /* Lock the object */
1075 apObj[auiIndices[i]] = GDIOBJ_LockObject(ahObj[auiIndices[i]], objt);
1076
1077 /* Check for failure */
1078 if (apObj[auiIndices[i]] == NULL)
1079 {
1080 /* Cleanup */
1081 while (i--)
1082 {
1083 if (apObj[auiIndices[i]])
1084 GDIOBJ_vUnlockObject(apObj[auiIndices[i]]);
1085 }
1086 return FALSE;
1087 }
1088 }
1089
1090 return TRUE;
1091}
1092
1093PVOID
1094NTAPI
1096{
1097 ULONG ulIndex = GDI_HANDLE_GET_INDEX(pobj->hHmgr);
1098 return gpentHmgr[ulIndex].pUser;
1099}
1100
1101VOID
1102NTAPI
1104{
1105 ULONG ulIndex;
1106
1107 ASSERT(pobj->hHmgr);
1108
1109 /* Get the handle index */
1110 ulIndex = GDI_HANDLE_GET_INDEX(pobj->hHmgr);
1111
1112 /* Set pointer to the usermode attribute */
1113 gpentHmgr[ulIndex].pUser = pvObjAttr;
1114}
1115
1116VOID
1117NTAPI
1119{
1120 ULONG ulIndex;
1121
1122 /* Set the object's delete flag */
1124 DBG_LOGEVENT(&pobj->slhLog, EVENT_DELETE, 0);
1125
1126 /* Get the handle index */
1127 ulIndex = GDI_HANDLE_GET_INDEX(pobj->hHmgr);
1128 if (ulIndex)
1129 {
1130 /* Reset the handle valid bit */
1132
1133 /* Check if the object is exclusively locked */
1134 if (pobj->cExclusiveLock != 0)
1135 {
1136 /* Reset lock owner and lock count */
1137 pobj->dwThreadId = 0;
1138 pobj->cExclusiveLock = 0;
1139
1140 /* Release the pushlock and reenable APCs */
1144 }
1145 }
1146
1147 /* Dereference the object (will take care of deletion) */
1149}
1150
1151BOOL
1152NTAPI
1154{
1155 PENTRY pentry;
1156
1157 pentry = ENTRY_ReferenceEntryByHandle(hobj, 0);
1158 if (!pentry) return FALSE;
1160 return TRUE;
1161}
1162
1163BOOL
1164NTAPI
1166{
1167 PENTRY pentry;
1168
1169 /* Check for stock objects */
1170 if (GDI_HANDLE_IS_STOCKOBJ(hobj))
1171 {
1172 DPRINT1("GreDeleteObject: Cannot delete stock object %p.\n", hobj);
1173 return FALSE;
1174 }
1175
1176 /* Reference the handle entry */
1177 pentry = ENTRY_ReferenceEntryByHandle(hobj, 0);
1178 if (!pentry)
1179 {
1180 DPRINT1("GreDeleteObject: Trying to delete invalid object %p\n", hobj);
1181 return FALSE;
1182 }
1183
1184 /* Check for public owner */
1185 if (pentry->ObjectOwner.ulObj == GDI_OBJ_HMGR_PUBLIC)
1186 {
1187 DPRINT1("GreDeleteObject: Trying to delete global object %p\n", hobj);
1189 return FALSE;
1190 }
1191
1192 /* Delete the object */
1194 return TRUE;
1195}
1196
1197ULONG
1198NTAPI
1200{
1201 ULONG ulIndex, ulOwner;
1202
1203 if (hobj == NULL)
1204 {
1205 DPRINT("GreGetObjectOwner: invalid NULL handle\n");
1207 }
1208
1209 /* Get the handle index */
1210 ulIndex = GDI_HANDLE_GET_INDEX(hobj);
1211
1212 /* Check if the handle is valid */
1213 if (ulIndex >= GDI_HANDLE_COUNT ||
1214 gpentHmgr[ulIndex].Objt == GDIObjType_DEF_TYPE ||
1215 ((ULONG_PTR)hobj >> 16) != gpentHmgr[ulIndex].FullUnique)
1216 {
1217 DPRINT1("GreGetObjectOwner: invalid handle 0x%p.\n", hobj);
1219 }
1220
1221 /* Get the object owner */
1222 ulOwner = gpentHmgr[ulIndex].ObjectOwner.ulObj;
1223
1224 if (ulOwner == HandleToUlong(PsGetCurrentProcessId()))
1225 return GDI_OBJ_HMGR_POWNED;
1226
1227 if (ulOwner == GDI_OBJ_HMGR_PUBLIC)
1228 return GDI_OBJ_HMGR_PUBLIC;
1229
1231}
1232
1233BOOL
1234NTAPI
1236 HGDIOBJ hobj,
1237 ULONG ulOwner,
1238 ULONG Flags)
1239{
1240 PENTRY pentry;
1241
1242 /* Check for stock objects */
1243 if (GDI_HANDLE_IS_STOCKOBJ(hobj))
1244 {
1245 DPRINT("GreSetObjectOwner: Got stock object %p\n", hobj);
1246 return FALSE;
1247 }
1248
1249 /* Reference the handle entry */
1250 pentry = ENTRY_ReferenceEntryByHandle(hobj, Flags);
1251 if (!pentry)
1252 {
1253 DPRINT("GreSetObjectOwner: Invalid handle 0x%p.\n", hobj);
1254 return FALSE;
1255 }
1256
1257 /* Call internal function */
1258 GDIOBJ_vSetObjectOwner(pentry->einfo.pobj, ulOwner);
1259
1260 /* Dereference the object */
1262
1263 return TRUE;
1264}
1265
1266BOOL
1267NTAPI
1269 HGDIOBJ hobj,
1270 ULONG ulOwner)
1271{
1272 return GreSetObjectOwnerEx(hobj, ulOwner, 0);
1273}
1274
1275INT
1276NTAPI
1278 IN HGDIOBJ hobj,
1279 IN INT cbCount,
1280 OUT PVOID pvBuffer)
1281{
1282 PVOID pvObj;
1283 UCHAR objt;
1284 INT iResult = 0;
1285
1286 /* Verify object type */
1287 objt = ((ULONG_PTR)hobj >> 16) & 0x1f;
1288 if (objt != GDIObjType_BRUSH_TYPE &&
1289 objt != GDIObjType_SURF_TYPE &&
1290 objt != GDIObjType_LFONT_TYPE &&
1291 objt != GDIObjType_PAL_TYPE)
1292 {
1293 DPRINT1("GreGetObject: Invalid object type\n");
1294 return 0;
1295 }
1296
1297 pvObj = GDIOBJ_ReferenceObjectByHandle(hobj, objt);
1298 if (!pvObj)
1299 {
1300 DPRINT("GreGetObject: Could not lock object\n");
1301 return 0;
1302 }
1303
1304 switch (GDI_HANDLE_GET_TYPE(hobj))
1305 {
1308 iResult = PEN_GetObject(pvObj, cbCount, pvBuffer);
1309 break;
1310
1312 iResult = BRUSH_GetObject(pvObj, cbCount, pvBuffer);
1313 break;
1314
1316 iResult = BITMAP_GetObject(pvObj, cbCount, pvBuffer);
1317 break;
1318
1320 iResult = FontGetObject(pvObj, cbCount, pvBuffer);
1321 break;
1322
1324 iResult = PALETTE_GetObject(pvObj, cbCount, pvBuffer);
1325 break;
1326
1327 default:
1328 DPRINT1("GDI object type of 0x%p not implemented\n", hobj);
1329 break;
1330 }
1331
1333 return iResult;
1334}
1335
1336W32KAPI
1337INT
1340 IN HANDLE hobj,
1341 IN INT cjBufferSize,
1343{
1344 UINT iResult, cjMaxSize;
1345 union
1346 {
1347 BITMAP bitmap;
1348 DIBSECTION dibsection;
1349 LOGPEN logpen;
1350 LOGBRUSH logbrush;
1351 LOGFONTW logfontw;
1352 EXTLOGFONTW extlogfontw;
1353 ENUMLOGFONTEXDVW enumlogfontexdvw;
1354 } object;
1355
1356 /* Normalize to the largest supported object size */
1357 cjMaxSize = min((UINT)cjBufferSize, sizeof(object));
1358
1359 /* Now do the actual call */
1360 iResult = GreGetObject(hobj, cjMaxSize, lpBuffer ? &object : NULL);
1361
1362 /* Check if we have a buffer and data */
1363 if ((lpBuffer != NULL) && (iResult != 0))
1364 {
1365 /* Enter SEH for buffer transfer */
1366 _SEH2_TRY
1367 {
1368 /* Probe the buffer and copy it */
1369 cjMaxSize = min(cjMaxSize, iResult);
1370 ProbeForWrite(lpBuffer, cjMaxSize, sizeof(WORD));
1371 RtlCopyMemory(lpBuffer, &object, cjMaxSize);
1372 }
1374 {
1375 /* Clear the return value.
1376 * Do *NOT* set last error here! */
1377 iResult = 0;
1378 }
1379 _SEH2_END;
1380 }
1381
1382 /* Return the count */
1383 return iResult;
1384}
1385
1386W32KAPI
1387HANDLE
1390 IN ULONG ulType)
1391{
1392 POBJ pObject;
1393 HANDLE handle;
1394
1395 /* Check if ulType is valid */
1399 {
1400 DPRINT1("NtGdiCreateClientObj: Invalid object type 0x%lx.\n", ulType);
1401 return NULL;
1402 }
1403
1404 /* Allocate a new object */
1406 sizeof(CLIENTOBJ),
1408 if (!pObject)
1409 {
1410 DPRINT1("NtGdiCreateClientObj: Could not allocate a clientobj.\n");
1411 return NULL;
1412 }
1413
1414 /* Set the real object type */
1416
1417 /* Create a handle */
1419 if (!handle)
1420 {
1421 DPRINT1("NtGdiCreateClientObj: Could not create a handle.\n");
1423 return NULL;
1424 }
1425
1426 /* Unlock it */
1428
1429 return handle;
1430}
1431
1432W32KAPI
1433BOOL
1436 IN HANDLE hobj)
1437{
1438 /* We first need to get the real type from the handle */
1440
1441 /* Check if it's really a CLIENTOBJ */
1443 {
1444 /* FIXME: SetLastError? */
1445 return FALSE;
1446 }
1447
1448 return GreDeleteObject(hobj);
1449}
1450
1451
1452
1454
1457{
1458 if (ExpectedType == GDI_OBJECT_TYPE_DONTCARE)
1459 ExpectedType = GDI_HANDLE_GET_TYPE(hObj);
1460 return GDIOBJ_ReferenceObjectByHandle(hObj, (ExpectedType >> 16) & 0x1f);
1461}
1462
1463// This function is not safe to use with concurrent deleting attempts
1464// That shouldn't be a problem, since we don't have any processes yet,
1465// that could delete the handle
1466BOOL
1467NTAPI
1469{
1470 PENTRY pentry;
1471 POBJ pobj;
1472
1473 /* Reference the handle entry */
1474 pentry = ENTRY_ReferenceEntryByHandle(*phObj, 0);
1475 if (!pentry)
1476 {
1477 DPRINT1("GDIOBJ: Requested handle 0x%p is not valid.\n", *phObj);
1478 return FALSE;
1479 }
1480
1481 /* Update the entry */
1483 pentry->ObjectOwner.ulObj = 0;
1484
1485 /* Get the pointer to the BASEOBJECT */
1486 pobj = pentry->einfo.pobj;
1487
1488 /* Calculate the new handle */
1490
1491 /* Return the new handle */
1492 *phObj = pobj->hHmgr;
1493
1494 /* Dereference the handle */
1496
1497 return TRUE;
1498}
1499
1500BOOL
1501NTAPI
1503{
1504 PENTRY pentry;
1505 POBJ pobj;
1506
1507 /* Reference the handle entry */
1508 pentry = ENTRY_ReferenceEntryByHandle(*phObj, 0);
1509 if (!pentry)
1510 {
1511 DPRINT1("GDIOBJ: Requested handle 0x%p is not valid.\n", *phObj);
1512 return FALSE;
1513 }
1514
1515 /* Update the entry */
1516 pentry->FullUnique &= ~GDI_ENTRY_STOCK_MASK;
1518
1519 /* Get the pointer to the BASEOBJECT */
1520 pobj = pentry->einfo.pobj;
1521
1522 /* Calculate the new handle */
1523 pobj->hHmgr = (HGDIOBJ)((ULONG_PTR)pobj->hHmgr & ~GDI_HANDLE_STOCK_MASK);
1524
1525 /* Return the new handle */
1526 *phObj = pobj->hHmgr;
1527
1528 /* Dereference the handle */
1530
1531 return TRUE;
1532}
1533
1534POBJ NTAPI
1536{
1537 POBJ pobj;
1538 FLONG fl = 0;
1539 UCHAR objt = (ObjectType >> 16) & 0xFF;
1540
1541 if ((objt == GDIObjType_DC_TYPE && cjSize == sizeof(DC)) ||
1542 (objt == GDIObjType_PAL_TYPE && cjSize == sizeof(PALETTE)) ||
1543 (objt == GDIObjType_RGN_TYPE && cjSize == sizeof(REGION)) ||
1544 (objt == GDIObjType_SURF_TYPE && cjSize == sizeof(SURFACE)) ||
1545 (objt == GDIObjType_PATH_TYPE && cjSize == sizeof(PATH)))
1546 {
1548 }
1549
1550 pobj = GDIOBJ_AllocateObject(objt, cjSize, fl);
1551 if (!pobj)
1552 {
1553 return NULL;
1554 }
1555
1557 {
1558 GDIOBJ_vFreeObject(pobj);
1559 return NULL;
1560 }
1561 return pobj;
1562}
1563
1566{
1567 PVOID pvMappedView = NULL;
1569 LARGE_INTEGER liOffset;
1570 SIZE_T cjViewSize = sizeof(GDI_HANDLE_TABLE);
1571
1572 liOffset.QuadPart = 0;
1573
1575 ASSERT(pProcess != NULL);
1576
1578 pProcess,
1579 &pvMappedView,
1580 0,
1581 0,
1582 &liOffset,
1583 &cjViewSize,
1584 ViewUnmap,
1587
1588 if (!NT_SUCCESS(Status))
1589 return NULL;
1590
1591 return pvMappedView;
1592}
1593
1594BOOL NTAPI
1596{
1597 PENTRY pentry;
1598 ULONG ulIndex;
1600 PPROCESSINFO ppi;
1601
1602 DPRINT("CleanupForProcess prochandle %p Pid %p\n",
1603 Process, Process->UniqueProcessId);
1604
1606
1607 /* Get the current process Id */
1609
1610 /* Loop all handles in the handle table */
1611 for (ulIndex = RESERVE_ENTRIES_COUNT; ulIndex < gulFirstUnused; ulIndex++)
1612 {
1613 pentry = &gpentHmgr[ulIndex];
1614
1615 /* Check if the object is owned by the process */
1616 if (pentry->ObjectOwner.ulObj == dwProcessId)
1617 {
1618 ASSERT(pentry->einfo.pobj->cExclusiveLock == 0);
1619
1620 /* Reference the object and delete it */
1623 }
1624 }
1625
1626#if DBG
1628#endif
1629
1631 DPRINT("Completed cleanup for process %p\n", Process->UniqueProcessId);
1632 if (ppi->GDIHandleCount != 0)
1633 {
1634 DPRINT1("Leaking %d handles!\n", ppi->GDIHandleCount);
1635 ASSERT(FALSE);
1636 }
1637
1638 /* Loop all handles in the handle table */
1639 for (ulIndex = RESERVE_ENTRIES_COUNT; ulIndex < gulFirstUnused; ulIndex++)
1640 {
1641 pentry = &gpentHmgr[ulIndex];
1642
1643 /* Check if the object is owned by the process */
1644 if (pentry->ObjectOwner.ulObj == dwProcessId)
1645 {
1646 DPRINT1("Leaking object. Index=%lx, type=0x%x, refcount=%lx\n",
1647 ulIndex, pentry->Objt, gpaulRefCount[ulIndex]);
1648 DBG_DUMP_EVENT_LIST(&pentry->einfo.pobj->slhLog);
1649 //DBG_CLEANUP_EVENT_LIST(&pentry->einfo.pobj->slhLog);
1650 ASSERT(FALSE);
1651 }
1652 }
1653
1654 return TRUE;
1655}
1656
1660{
1661 PPROCESSINFO ppi;
1662
1664 NT_ASSERT(ppi != NULL);
1665
1666 return ppi->pPoolBrushAttr;
1667}
1668
1669/* EOF */
NTSTATUS NTAPI MmMapViewInSessionSpace(IN PVOID Section, OUT PVOID *MappedBase, IN OUT PSIZE_T ViewSize)
Definition: section.c:2689
#define CODE_SEG(...)
#define InterlockedIncrement
Definition: armddk.h:53
#define InterlockedDecrement
Definition: armddk.h:52
LONG NTSTATUS
Definition: precomp.h:26
#define DPRINT1
Definition: precomp.h:8
#define UlongToHandle(ul)
Definition: basetsd.h:91
#define HandleToUlong(h)
Definition: basetsd.h:73
#define ULongToHandle(h)
Definition: basetsd.h:75
INT APIENTRY BITMAP_GetObject(SURFACE *psurf, INT Count, LPVOID buffer)
Definition: bitmaps.c:771
VOID NTAPI BRUSH_vDeleteObject(PVOID pvObject)
Definition: brush.cpp:263
INT FASTCALL BRUSH_GetObject(PBRUSH pbr, INT cjBuffer, LPLOGBRUSH plbBuffer)
Definition: brush.cpp:271
PGDI_POOL GetBrushAttrPool(VOID)
Definition: brush.hpp:16
#define STATUS_NO_MEMORY
Definition: d3dkmdt.h:51
VOID NTAPI DC_vCleanup(PVOID ObjectBody)
Definition: dclife.c:357
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
#define APIENTRY
Definition: api.h:79
#define PAGE_READONLY
Definition: compat.h:138
VOID NTAPI DRIVEROBJ_vCleanup(PVOID pObject)
DRIVEROBJ cleanup function.
Definition: driverobj.c:24
#define UlongToPtr(u)
Definition: config.h:106
#define ULONG_PTR
Definition: config.h:101
#define PtrToUlong(u)
Definition: config.h:107
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define NonPagedPool
Definition: env_spec_w32.h:307
#define PagedPool
Definition: env_spec_w32.h:308
#define ExInitializePushLock
Definition: ex.h:1016
FORCEINLINE VOID ExAcquirePushLockExclusive(PEX_PUSH_LOCK PushLock)
Definition: ex.h:1039
FORCEINLINE VOID ExReleasePushLockExclusive(PEX_PUSH_LOCK PushLock)
Definition: ex.h:1255
VOID NTAPI ProbeForWrite(IN PVOID Address, IN SIZE_T Length, IN ULONG Alignment)
Definition: exintrin.c:143
DWORD dwThreadId
Definition: fdebug.c:31
PsGetCurrentThreadId
Definition: CrNtStubs.h:8
unsigned short WORD
Definition: ntddk_ex.h:93
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
_Must_inspect_result_ _In_ PLARGE_INTEGER _In_ PLARGE_INTEGER _In_ ULONG _In_ PFILE_OBJECT _In_ PVOID Process
Definition: fsrtlfuncs.h:223
FxObject * pObject
#define GDI_OBJECT_TYPE_DONTCARE
Definition: gdi.h:64
#define GDI_HANDLE_STOCK_MASK
Definition: gdi.h:19
#define GDI_HANDLE_GET_INDEX(h)
Definition: gdi.h:28
#define GDI_HANDLE_GET_TYPE(h)
Definition: gdi.h:31
#define GDI_HANDLE_BASETYPE_MASK
Definition: gdi.h:18
#define GDI_HANDLE_COUNT
Definition: gdi.h:12
#define GDI_HANDLE_INDEX_MASK
Definition: gdi.h:16
#define GDI_HANDLE_IS_STOCKOBJ(h)
Definition: gdi.h:37
@ GDILoObjType_LO_FONT_TYPE
Definition: gdi_private.h:37
@ GDILoObjType_LO_PALETTE_TYPE
Definition: gdi_private.h:36
@ GDILoObjType_LO_CLIENTOBJ_TYPE
Definition: gdi_private.h:40
@ GDILoObjType_LO_BRUSH_TYPE
Definition: gdi_private.h:33
@ GDILoObjType_LO_BITMAP_TYPE
Definition: gdi_private.h:35
@ GDILoObjType_LO_METAFILE_TYPE
Definition: gdi_private.h:48
@ GDILoObjType_LO_METADC16_TYPE
Definition: gdi_private.h:49
@ GDILoObjType_LO_EXTPEN_TYPE
Definition: gdi_private.h:45
@ GDILoObjType_LO_METAFILE16_TYPE
Definition: gdi_private.h:47
@ GDILoObjType_LO_PEN_TYPE
Definition: gdi_private.h:44
#define DBG_LOGEVENT(pslh, type, val)
Definition: gdidebug.h:109
#define DBG_CLEANUP_EVENT_LIST(pslh)
Definition: gdidebug.h:112
#define DBG_DUMP_EVENT_LIST(pslh)
Definition: gdidebug.h:111
#define DBG_INITLOG(pslh)
Definition: gdidebug.h:110
BOOL NTAPI DbgGdiHTIntegrityCheck(VOID)
ULONG NTAPI DbgCaptureStackBackTace(_Out_writes_(cFramesToCapture) PVOID *ppvFrames, _In_ ULONG cFramesToSkip, _In_ ULONG cFramesToCapture)
@ BASEFLAG_READY_TO_DIE
Definition: gdiobj.h:61
@ BASEFLAG_LOOKASIDE
Definition: gdiobj.h:58
@ GDIOBJFLAG_IGNOREPID
Definition: gdiobj.h:72
VOID(NTAPI * GDICLEANUPPROC)(PVOID ObjectBody)
Definition: gdiobj.h:33
#define GDI_OBJECT_STACK_LEVELS
Definition: gdiobj.h:8
static const unsigned RESERVE_ENTRIES_COUNT
Definition: gdiobj.h:11
VOID(NTAPI * GDIOBJDELETEPROC)(PVOID ObjectBody)
Definition: gdiobj.h:34
struct _GDI_HANDLE_TABLE GDI_HANDLE_TABLE
Status
Definition: gdiplustypes.h:25
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
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
#define TIF_MOVESIZETRACKING
Definition: ntuser.h:278
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:90
#define InterlockedExchangeAdd
Definition: interlocked.h:196
#define InterlockedOr
Definition: interlocked.h:239
#define InterlockedCompareExchange
Definition: interlocked.h:119
#define InterlockedOr16
Definition: interlocked.h:254
#define InterlockedAnd
Definition: interlocked.h:77
#define KeLeaveCriticalRegion()
Definition: ke_x.h:119
#define KeEnterCriticalRegion()
Definition: ke_x.h:88
VOID NTAPI ExInitializePagedLookasideList(IN PPAGED_LOOKASIDE_LIST Lookaside, IN PALLOCATE_FUNCTION Allocate OPTIONAL, IN PFREE_FUNCTION Free OPTIONAL, IN ULONG Flags, IN SIZE_T Size, IN ULONG Tag, IN USHORT Depth)
Definition: lookas.c:270
#define ASSERT(a)
Definition: mode.c:44
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1109
ObjectType
Definition: metafile.c:81
static int cbCount
Definition: fiber.c:42
#define min(a, b)
Definition: monoChain.cc:55
#define __analysis_assume(expr)
Definition: ms_sal.h:2893
unsigned int UINT
Definition: ndis.h:50
_In_ UINT _In_ UINT _In_ PNDIS_PACKET Source
Definition: ndis.h:3169
#define SEC_COMMIT
Definition: mmtypes.h:100
#define SEC_NO_CHANGE
Definition: mmtypes.h:95
_Out_ LPWSTR lpBuffer
Definition: netsh.h:68
#define _In_
Definition: no_sal2.h:158
#define _Interlocked_operand_
Definition: no_sal2.h:410
#define PAGE_READWRITE
Definition: nt_native.h:1307
#define SECTION_ALL_ACCESS
Definition: nt_native.h:1296
@ ViewUnmap
Definition: nt_native.h:1282
unsigned long FLONG
Definition: ntbasedef.h:378
#define DBG_UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:330
#define W32KAPI
Definition: ntgdi.h:9
#define GDI_OBJ_HMGR_POWNED
Definition: ntgdihdl.h:117
#define GDI_OBJ_HMGR_PUBLIC
Definition: ntgdihdl.h:116
#define GDI_ENTRY_STOCK_MASK
Definition: ntgdihdl.h:33
#define GDI_OBJ_HMGR_RESTRICTED
Definition: ntgdihdl.h:119
#define GDI_OBJ_HMGR_NONE
Definition: ntgdihdl.h:118
@ GDIObjType_ICMLCS_TYPE
Definition: ntgdityp.h:129
@ GDIObjTypeTotal
Definition: ntgdityp.h:152
@ GDIObjType_PAL_TYPE
Definition: ntgdityp.h:128
@ GDIObjType_DC_TYPE
Definition: ntgdityp.h:121
@ GDIObjType_LFONT_TYPE
Definition: ntgdityp.h:130
@ GDIObjType_PATH_TYPE
Definition: ntgdityp.h:127
@ GDIObjType_BRUSH_TYPE
Definition: ntgdityp.h:136
@ GDIObjType_RGN_TYPE
Definition: ntgdityp.h:124
@ GDIObjType_SURF_TYPE
Definition: ntgdityp.h:125
@ GDIObjType_CLIENTOBJ_TYPE
Definition: ntgdityp.h:126
@ GDIObjType_DEF_TYPE
Definition: ntgdityp.h:120
PVOID NTAPI PsGetProcessWin32Process(PEPROCESS Process)
Definition: process.c:1193
NTSTATUS NTAPI PsLookupProcessByProcessId(IN HANDLE ProcessId, OUT PEPROCESS *Process)
Definition: process.c:919
PVOID NTAPI PsGetCurrentProcessWin32Process(VOID)
Definition: process.c:1183
HANDLE NTAPI PsGetCurrentProcessId(VOID)
Definition: process.c:1123
PVOID NTAPI PsGetCurrentThreadWin32Thread(VOID)
Definition: thread.c:805
struct _PATH PATH
short SHORT
Definition: pedump.c:59
long LONG
Definition: pedump.c:60
unsigned short USHORT
Definition: pedump.c:61
#define FL_ZERO_MEMORY
Definition: polytest.cpp:58
_In_ DWORD dwProcessId
Definition: shlwapi.h:193
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:82
#define _SEH2_END
Definition: pseh2_64.h:171
#define _SEH2_TRY
Definition: pseh2_64.h:71
struct _REGION REGION
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:4027
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:4674
#define STATUS_SUCCESS
Definition: shellext.h:65
#define DPRINT
Definition: sndvol32.h:73
Definition: polytest.cpp:41
HGDIOBJ hHmgr
Definition: gdiobj.h:40
USHORT BaseFlags
Definition: gdiobj.h:46
USHORT cExclusiveLock
Definition: gdiobj.h:45
DWORD dwThreadId
Definition: gdiobj.h:43
ULONG ulShareCount
Definition: gdiobj.h:42
EX_PUSH_LOCK pushlock
Definition: gdiobj.h:47
Definition: bl.h:1331
Definition: ntgdihdl.h:218
union _ENTRY::_OBJECTOWNER ObjectOwner
UCHAR Objt
Definition: ntgdihdl.h:236
PVOID pUser
Definition: ntgdihdl.h:238
union _ENTRY::_EINFO einfo
USHORT FullUnique
Definition: ntgdihdl.h:235
Definition: text.h:60
Definition: path.h:35
struct _GDI_POOL * pPoolBrushAttr
Definition: win32.h:293
Definition: region.h:8
ULONG cExclusiveLocks
Definition: win32.h:158
FLONG TIF_flags
Definition: win32.h:95
Definition: uimain.c:89
Definition: ps.c:97
uint32_t * PULONG
Definition: typedefs.h:59
#define NTAPI
Definition: typedefs.h:36
void * PVOID
Definition: typedefs.h:50
ULONG_PTR SIZE_T
Definition: typedefs.h:80
int32_t INT
Definition: typedefs.h:58
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define IN
Definition: typedefs.h:39
int32_t * PLONG
Definition: typedefs.h:58
uint32_t ULONG
Definition: typedefs.h:59
#define OUT
Definition: typedefs.h:40
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
struct _BASEOBJECT * pobj
Definition: ntgdihdl.h:221
HGDIOBJ hFree
Definition: ntgdihdl.h:222
ULONG ulObj
Definition: ntgdihdl.h:232
LONGLONG QuadPart
Definition: typedefs.h:114
_In_z_ PCWSTR _In_ ULONG ulType
Definition: ntuser.h:43
#define FORCEINLINE
Definition: wdftypes.h:67
VOID NTAPI SURFACE_vCleanup(PVOID ObjectBody)
Definition: surface.c:67
struct _SURFACE SURFACE
ULONG FASTCALL FontGetObject(_Inout_ PTEXTOBJ plfont, _In_ ULONG cjBuffer, _Out_ PVOID pvBuffer)
Definition: font.c:296
BOOL NTAPI GreSetObjectOwner(HGDIOBJ hobj, ULONG ulOwner)
Definition: gdiobj.c:1268
volatile ULONG gulFirstUnused
Definition: gdiobj.c:152
static VOID InitLookasideList(UCHAR objt, ULONG cjSize)
Definition: gdiobj.c:245
volatile ULONG gulFirstFree
Definition: gdiobj.c:151
@ REF_MASK_REUSE
Definition: gdiobj.c:138
@ REF_INC_REUSE
Definition: gdiobj.c:139
@ REF_MASK_COUNT
Definition: gdiobj.c:141
@ REF_MASK_INUSE
Definition: gdiobj.c:142
@ REF_MASK_VALID
Definition: gdiobj.c:140
static PENTRY ENTRY_pentPopFreeEntry(VOID)
Definition: gdiobj.c:382
BOOL NTAPI GDIOBJ_ConvertToStockObj(HGDIOBJ *phObj)
Definition: gdiobj.c:1468
POBJ NTAPI GDIOBJ_ReferenceObjectByHandle(HGDIOBJ hobj, UCHAR objt)
Definition: gdiobj.c:698
VOID NTAPI GDIOBJ_vDereferenceObject(POBJ pobj)
Definition: gdiobj.c:638
PVOID NTAPI GDIOBJ_pvGetObjectAttr(POBJ pobj)
Definition: gdiobj.c:1095
static PVOID gpvGdiHdlTblSection
Definition: gdiobj.c:148
BOOL NTAPI GreSetObjectOwnerEx(HGDIOBJ hobj, ULONG ulOwner, ULONG Flags)
Definition: gdiobj.c:1235
BOOL NTAPI GDIOBJ_ConvertFromStockObj(HGDIOBJ *phObj)
Definition: gdiobj.c:1502
FORCEINLINE ULONG InterlockedReadUlong(_In_ _Interlocked_operand_ ULONG volatile *Source)
Definition: gdiobj.c:55
static VOID IncrementGdiHandleCount(ULONG ulProcessId)
Definition: gdiobj.c:348
static VOID NTAPI GDIOBJ_vCleanup(PVOID ObjectBody)
Definition: gdiobj.c:238
VOID NTAPI GDIOBJ_vFreeObject(POBJ pobj)
Definition: gdiobj.c:603
static PPAGED_LOOKASIDE_LIST gpaLookasideList
Definition: gdiobj.c:153
W32KAPI INT APIENTRY NtGdiExtGetObjectW(IN HANDLE hobj, IN INT cjBufferSize, OUT LPVOID lpBuffer)
Definition: gdiobj.c:1339
FORCEINLINE void INCREASE_THREAD_LOCK_COUNT(_In_ HANDLE hobj)
Definition: gdiobj.c:63
W32KAPI BOOL APIENTRY NtGdiDeleteClientObj(IN HANDLE hobj)
Definition: gdiobj.c:1435
HGDIOBJ NTAPI GDIOBJ_hInsertObject(POBJ pobj, ULONG ulOwner)
Definition: gdiobj.c:919
VOID NTAPI GDIOBJ_vSetObjectAttr(POBJ pobj, PVOID pvObjAttr)
Definition: gdiobj.c:1103
FORCEINLINE void DECREASE_THREAD_LOCK_COUNT(_In_ HANDLE hobj)
Definition: gdiobj.c:79
static HGDIOBJ ENTRY_hInsertObject(PENTRY pentry, POBJ pobj, UCHAR objt, ULONG ulOwner)
Definition: gdiobj.c:546
static VOID DecrementGdiHandleCount(ULONG ulProcessId)
Definition: gdiobj.c:365
BOOL NTAPI GreDeleteObject(HGDIOBJ hobj)
Definition: gdiobj.c:1165
BOOL NTAPI GDIOBJ_bLockMultipleObjects(IN ULONG ulCount, IN HGDIOBJ *ahObj, OUT PGDIOBJ *apObj, IN UCHAR objt)
Definition: gdiobj.c:1038
BOOL NTAPI GDI_CleanupForProcess(struct _EPROCESS *Process)
Definition: gdiobj.c:1595
VOID NTAPI GDIOBJ_vSetObjectOwner(POBJ pobj, ULONG ulNewOwner)
Definition: gdiobj.c:972
#define GDIOBJ_POOL_TAG(type)
Definition: gdiobj.c:134
PENTRY gpentHmgr
Definition: gdiobj.c:149
#define ASSERT_SHARED_OBJECT_TYPE(objt)
Definition: gdiobj.c:125
PGDIOBJ NTAPI GDIOBJ_LockObject(HGDIOBJ hobj, UCHAR objt)
Definition: gdiobj.c:833
ULONG NTAPI GreGetObjectOwner(HGDIOBJ hobj)
Definition: gdiobj.c:1199
static const GDICLEANUPPROC apfnCleanup[]
Definition: gdiobj.c:159
NTSTATUS NTAPI InitGdiHandleTable(void)
Definition: gdiobj.c:259
static const GDIOBJDELETEPROC apfnDelete[]
Definition: gdiobj.c:197
FORCEINLINE VOID IncrementCurrentProcessGdiHandleCount(void)
Definition: gdiobj.c:332
POBJ NTAPI GDIOBJ_AllocateObject(UCHAR objt, ULONG cjSize, FLONG fl)
Definition: gdiobj.c:569
BOOL NTAPI GreIsHandleValid(HGDIOBJ hobj)
Definition: gdiobj.c:1153
PVOID NTAPI GDI_MapHandleTable(PEPROCESS pProcess)
Definition: gdiobj.c:1565
PULONG gpaulRefCount
Definition: gdiobj.c:150
static VOID ENTRY_vPushFreeEntry(PENTRY pentFree)
Definition: gdiobj.c:439
POBJ NTAPI GDIOBJ_AllocObjWithHandle(ULONG ObjectType, ULONG cjSize)
Definition: gdiobj.c:1535
PGDIOBJ NTAPI GDIOBJ_ShareLockObj(HGDIOBJ hObj, DWORD ExpectedType)
Definition: gdiobj.c:1456
W32KAPI HANDLE APIENTRY NtGdiCreateClientObj(IN ULONG ulType)
Definition: gdiobj.c:1389
INT NTAPI GreGetObject(IN HGDIOBJ hobj, IN INT cbCount, OUT PVOID pvBuffer)
Definition: gdiobj.c:1277
#define ASSERT_TRYLOCK_OBJECT_TYPE(objt)
Definition: gdiobj.c:127
VOID NTAPI GDIOBJ_vUnlockObject(POBJ pobj)
Definition: gdiobj.c:887
PGDI_HANDLE_TABLE GdiHandleTable
Definition: gdiobj.c:1453
VOID NTAPI GDIOBJ_vDeleteObject(POBJ pobj)
Definition: gdiobj.c:1118
FORCEINLINE VOID DecrementCurrentProcessGdiHandleCount(void)
Definition: gdiobj.c:340
#define ASSERT_LOCK_ORDER(hobj)
Definition: gdiobj.c:124
#define ASSERT_EXCLUSIVE_OBJECT_TYPE(objt)
Definition: gdiobj.c:126
PGDIOBJ NTAPI GDIOBJ_TryLockObject(HGDIOBJ hobj, UCHAR objt)
Definition: gdiobj.c:764
static PENTRY ENTRY_ReferenceEntryByHandle(HGDIOBJ hobj, FLONG fl)
Definition: gdiobj.c:478
VOID NTAPI GDIOBJ_vReferenceObjectByPointer(POBJ pobj)
Definition: gdiobj.c:741
FORCEINLINE BOOLEAN ExTryAcquirePushLockExclusive(PEX_PUSH_LOCK PushLock)
Definition: misc.h:117
INT FASTCALL PALETTE_GetObject(PPALETTE ppal, INT cbCount, LPLOGBRUSH lpBuffer)
Definition: palette.c:247
VOID NTAPI PALETTE_vCleanup(PVOID ObjectBody)
Definition: palette.c:236
struct _PALETTE PALETTE
INT APIENTRY PEN_GetObject(PBRUSH pbrushPen, INT cbCount, PLOGPEN pBuffer)
Definition: pen.c:290
VOID NTAPI REGION_vCleanup(PVOID ObjectBody)
Definition: region.c:2433
#define TAG_GDIHNDTBLE
Definition: tags.h:16
#define GDITAG_HMGR_LOOKASIDE_START
Definition: tags.h:131
_In_ FLONG fl
Definition: winddi.h:1279
_In_ ULONG cjSize
Definition: winddi.h:3634
void * HGDIOBJ
Definition: windef.h:59
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
struct LOOKASIDE_ALIGN _PAGED_LOOKASIDE_LIST PAGED_LOOKASIDE_LIST
struct LOOKASIDE_ALIGN _PAGED_LOOKASIDE_LIST * PPAGED_LOOKASIDE_LIST
#define ObDereferenceObject
Definition: obfuncs.h:203
#define PsGetCurrentProcess
Definition: psfuncs.h:17
#define NT_ASSERT
Definition: rtlfuncs.h:3327
unsigned char UCHAR
Definition: xmlstorage.h:181