ReactOS 0.4.16-dev-716-g2b2bdab
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;
482
483 /* Get the handle index and check if its too big */
484 ulIndex = GDI_HANDLE_GET_INDEX(hobj);
485
486 /* Get pointer to the entry */
487 pentry = &gpentHmgr[ulIndex];
488
489 /* Get the current reference count */
490 cOldRefs = gpaulRefCount[ulIndex];
491
492 do
493 {
494 /* Check if the slot is deleted */
495 if ((cOldRefs & REF_MASK_VALID) == 0)
496 {
497 DPRINT("GDIOBJ: Slot is not valid: 0x%lx, hobh=%p\n", cOldRefs, hobj);
498 return NULL;
499 }
500
501 /* Check if the unique value matches */
502 if (pentry->FullUnique != (USHORT)((ULONG_PTR)hobj >> 16))
503 {
504 DPRINT("GDIOBJ: Wrong unique value. Handle: 0x%4x, entry: 0x%4x\n",
505 (USHORT)((ULONG_PTR)hobj >> 16), pentry->FullUnique);
506 return NULL;
507 }
508
509 /* Check if the object owner is this process or public */
510 if (!(fl & GDIOBJFLAG_IGNOREPID) &&
513 {
514 DPRINT("GDIOBJ: Cannot reference foreign handle %p, pentry=%p:%lx.\n",
515 hobj, pentry, pentry->ObjectOwner.ulObj);
516 return NULL;
517 }
518
519 /* Try to atomically increment the reference count */
520 cNewRefs = cOldRefs + 1;
521 cOldRefs = InterlockedCompareExchange((PLONG)&gpaulRefCount[ulIndex],
522 cNewRefs,
523 cOldRefs);
524 }
525 while (cNewRefs != cOldRefs + 1);
526
527 /* Integrity checks */
528 ASSERT((pentry->FullUnique & 0x1f) == pentry->Objt);
529 ASSERT(pentry->einfo.pobj != NULL);
530
531 /* Check if lower 32 bits match, the upper 32 bits are ignored */
532 ASSERT(pentry->einfo.pobj->hHmgr == UlongToPtr(PtrToUlong(hobj)));
533
534 return pentry;
535}
536
537static
539ENTRY_hInsertObject(PENTRY pentry, POBJ pobj, UCHAR objt, ULONG ulOwner)
540{
541 ULONG ulIndex;
542
543 /* Calculate the handle index */
544 ulIndex = pentry - gpentHmgr;
545
546 /* Update the fields in the ENTRY */
547 pentry->einfo.pobj = pobj;
548 pentry->Objt = objt & 0x1f;
549 pentry->FullUnique = (pentry->FullUnique & 0xff00) | objt;
550 pentry->ObjectOwner.ulObj = ulOwner;
551
552 /* Make the handle valid with 1 reference */
553 ASSERT((gpaulRefCount[ulIndex] & REF_MASK_INUSE) == 0);
555
556 /* Return the handle */
557 return (HGDIOBJ)(((ULONG_PTR)pentry->FullUnique << 16) | ulIndex);
558}
559
560POBJ
561NTAPI
563{
564 POBJ pobj;
565
567 {
568 /* Allocate the object from a lookaside list */
569 pobj = ExAllocateFromPagedLookasideList(&gpaLookasideList[objt & 0x1f]);
570 }
571 else
572 {
573 /* Allocate the object from paged pool */
575 }
576
577 if (!pobj) return NULL;
578
579 /* Initialize the object */
580 RtlZeroMemory(pobj, cjSize);
581 pobj->hHmgr = (HGDIOBJ)((ULONG_PTR)objt << 16);
582 pobj->cExclusiveLock = 0;
583 pobj->ulShareCount = 1;
584 pobj->BaseFlags = fl & 0xffff;
585 DBG_INITLOG(&pobj->slhLog);
586 DBG_LOGEVENT(&pobj->slhLog, EVENT_ALLOCATE, 0);
587#if DBG_ENABLE_GDIOBJ_BACKTRACES
588 DbgCaptureStackBackTace(pobj->apvBackTrace, 1, GDI_OBJECT_STACK_LEVELS);
589#endif /* GDI_DEBUG */
590
591 return pobj;
592}
593
594VOID
595NTAPI
597{
598 UCHAR objt;
599
600 DBG_CLEANUP_EVENT_LIST(&pobj->slhLog);
601
602 /* Get the object type */
603 objt = ((ULONG_PTR)pobj->hHmgr >> 16) & 0x1f;
604
605 /* Check if we have a delete procedure (for C++ based objects) */
606 if (apfnDelete[objt] != NULL)
607 {
608 /* Invoke the delete procedure */
609 apfnDelete[objt](pobj);
610 }
611 else
612 {
613 /* Call the cleanup procedure */
614 NT_ASSERT(apfnCleanup[objt]);
615 apfnCleanup[objt](pobj);
616
617 /* Check if the object is allocated from a lookaside list */
618 if (pobj->BaseFlags & BASEFLAG_LOOKASIDE)
619 {
620 ExFreeToPagedLookasideList(&gpaLookasideList[objt], pobj);
621 }
622 else
623 {
625 }
626 }
627}
628
629VOID
630NTAPI
632{
633 ULONG cRefs, ulIndex;
634
635 /* Calculate the index */
636 ulIndex = GDI_HANDLE_GET_INDEX(pobj->hHmgr);
637
638 /* Check if the object has a handle */
639 if (ulIndex)
640 {
641 /* Decrement reference count */
642 if ((gpaulRefCount[ulIndex] & REF_MASK_COUNT) == 0)
643 {
644 DBG_DUMP_EVENT_LIST(&pobj->slhLog);
645 }
646 ASSERT((gpaulRefCount[ulIndex] & REF_MASK_COUNT) > 0);
647 cRefs = InterlockedDecrement((LONG*)&gpaulRefCount[ulIndex]);
648 DBG_LOGEVENT(&pobj->slhLog, EVENT_DEREFERENCE, cRefs);
649
650 /* Check if we reached 0 and handle bit is not set */
651 if ((cRefs & REF_MASK_INUSE) == 0)
652 {
653 /* Make sure it's ok to delete the object */
655
656 /* Check if the handle was process owned */
657 if (gpentHmgr[ulIndex].ObjectOwner.ulObj != GDI_OBJ_HMGR_PUBLIC &&
659 {
660 /* Decrement the process handle count */
661 ASSERT(gpentHmgr[ulIndex].ObjectOwner.ulObj ==
664 }
665
666 /* Push entry to the free list */
668
669 /* Free the object */
670 GDIOBJ_vFreeObject(pobj);
671 }
672 }
673 else
674 {
675 /* Decrement the objects reference count */
676 ASSERT(pobj->ulShareCount > 0);
677 cRefs = InterlockedDecrement((LONG*)&pobj->ulShareCount);
678 DBG_LOGEVENT(&pobj->slhLog, EVENT_DEREFERENCE, cRefs);
679
680 /* Check if we reached 0 */
681 if (cRefs == 0)
682 {
683 /* Free the object */
684 GDIOBJ_vFreeObject(pobj);
685 }
686 }
687}
688
689POBJ
690NTAPI
692 HGDIOBJ hobj,
693 UCHAR objt)
694{
695 PENTRY pentry;
696 POBJ pobj;
697
698 /* Check if the handle type matches */
700 if ((((ULONG_PTR)hobj >> 16) & 0x1f) != objt)
701 {
702 DPRINT("GDIOBJ: Wrong type. handle=%p, type=%x\n", hobj, objt);
703 return NULL;
704 }
705
706 /* Reference the handle entry */
707 pentry = ENTRY_ReferenceEntryByHandle(hobj, 0);
708 if (!pentry)
709 {
710 DPRINT("GDIOBJ: Requested handle 0x%p is not valid.\n", hobj);
711 return NULL;
712 }
713
714 /* Get the pointer to the BASEOBJECT */
715 pobj = pentry->einfo.pobj;
716
717 /* Check if the object is exclusively locked */
718 if (pobj->cExclusiveLock != 0)
719 {
720 DPRINT1("GDIOBJ: Cannot reference object %p with exclusive lock.\n", hobj);
722 DBG_DUMP_EVENT_LIST(&pobj->slhLog);
723 return NULL;
724 }
725
726 DBG_LOGEVENT(&pobj->slhLog, EVENT_REFERENCE, gpaulRefCount[pentry - gpentHmgr]);
727
728 /* All is well, return the object */
729 return pobj;
730}
731
732VOID
733NTAPI
735{
736 ULONG cRefs;
737
738 /* Check if the object has a handle */
739 if (GDI_HANDLE_GET_INDEX(pobj->hHmgr))
740 {
741 /* Increase the handle's reference count */
742 ULONG ulIndex = GDI_HANDLE_GET_INDEX(pobj->hHmgr);
743 ASSERT((gpaulRefCount[ulIndex] & REF_MASK_COUNT) > 0);
744 cRefs = InterlockedIncrement((LONG*)&gpaulRefCount[ulIndex]);
745 }
746 else
747 {
748 /* Increase the object's reference count */
749 cRefs = InterlockedIncrement((LONG*)&pobj->ulShareCount);
750 }
751
752 DBG_LOGEVENT(&pobj->slhLog, EVENT_REFERENCE, cRefs);
753}
754
756NTAPI
758 HGDIOBJ hobj,
759 UCHAR objt)
760{
761 PENTRY pentry;
762 POBJ pobj;
764
765 /* Check if the handle type matches */
767 if ((((ULONG_PTR)hobj >> 16) & 0x1f) != objt)
768 {
769 DPRINT("Wrong object type: hobj=0x%p, objt=0x%x\n", hobj, objt);
770 return NULL;
771 }
772
773 /* Make sure lock order is correct */
774 ASSERT_LOCK_ORDER(objt);
775
776 /* Reference the handle entry */
777 pentry = ENTRY_ReferenceEntryByHandle(hobj, 0);
778 if (!pentry)
779 {
780 DPRINT("GDIOBJ: Requested handle 0x%p is not valid.\n", hobj);
781 return NULL;
782 }
783
784 /* Get the pointer to the BASEOBJECT */
785 pobj = pentry->einfo.pobj;
786
787 /* Check if we already own the lock */
789 if (pobj->dwThreadId != dwThreadId)
790 {
791 /* Disable APCs and try acquiring the push lock */
794 {
795 ULONG cRefs, ulIndex;
796 /* Already owned. Clean up and leave. */
798
799 /* Calculate the index */
800 ulIndex = GDI_HANDLE_GET_INDEX(pobj->hHmgr);
801
802 /* Decrement reference count */
803 ASSERT((gpaulRefCount[ulIndex] & REF_MASK_COUNT) > 0);
804 cRefs = InterlockedDecrement((LONG*)&gpaulRefCount[ulIndex]);
805 ASSERT(cRefs & REF_MASK_VALID);
806
807 return NULL;
808 }
809
810 /* Set us as lock owner */
811 ASSERT(pobj->dwThreadId == 0);
812 pobj->dwThreadId = dwThreadId;
813 }
814
815 /* Increase lock count */
816 pobj->cExclusiveLock++;
818 DBG_LOGEVENT(&pobj->slhLog, EVENT_LOCK, 0);
819
820 /* Return the object */
821 return pobj;
822}
823
825NTAPI
827 HGDIOBJ hobj,
828 UCHAR objt)
829{
830 PENTRY pentry;
831 POBJ pobj;
833
834 /* Check if the handle type matches */
836 if ((((ULONG_PTR)hobj >> 16) & 0x1f) != objt)
837 {
838 DPRINT("Wrong object type: hobj=0x%p, objt=0x%x\n", hobj, objt);
839 return NULL;
840 }
841
842 /* Make sure lock order is correct */
843 ASSERT_LOCK_ORDER(objt);
844
845 /* Reference the handle entry */
846 pentry = ENTRY_ReferenceEntryByHandle(hobj, 0);
847 if (!pentry)
848 {
849 DPRINT("GDIOBJ: Requested handle 0x%p is not valid.\n", hobj);
850 return NULL;
851 }
852
853 /* Get the pointer to the BASEOBJECT */
854 pobj = pentry->einfo.pobj;
855
856 /* Check if we already own the lock */
858 if (pobj->dwThreadId != dwThreadId)
859 {
860 /* Disable APCs and acquire the push lock */
863
864 /* Set us as lock owner */
865 ASSERT(pobj->dwThreadId == 0);
866 pobj->dwThreadId = dwThreadId;
867 }
868
869 /* Increase lock count */
870 pobj->cExclusiveLock++;
872 DBG_LOGEVENT(&pobj->slhLog, EVENT_LOCK, 0);
873
874 /* Return the object */
875 return pobj;
876}
877
878VOID
879NTAPI
881{
882 ULONG cRefs, ulIndex;
883 ASSERT(pobj->cExclusiveLock > 0);
884
885 /* Decrease lock count */
886 pobj->cExclusiveLock--;
888 DBG_LOGEVENT(&pobj->slhLog, EVENT_UNLOCK, 0);
889
890 /* Check if this was the last lock */
891 if (pobj->cExclusiveLock == 0)
892 {
893 /* Reset lock owner */
894 pobj->dwThreadId = 0;
895
896 /* Release the pushlock and reenable APCs */
899 }
900
901 /* Calculate the index */
902 ulIndex = GDI_HANDLE_GET_INDEX(pobj->hHmgr);
903
904 /* Decrement reference count */
905 ASSERT((gpaulRefCount[ulIndex] & REF_MASK_COUNT) > 0);
906 cRefs = InterlockedDecrement((LONG*)&gpaulRefCount[ulIndex]);
907 ASSERT(cRefs & REF_MASK_VALID);
908}
909
911NTAPI
913 POBJ pobj,
914 ULONG ulOwner)
915{
916 PENTRY pentry;
917 UCHAR objt;
918
919 /* Must have no handle and only one reference */
920 ASSERT(GDI_HANDLE_GET_INDEX(pobj->hHmgr) == 0);
921 ASSERT(pobj->cExclusiveLock == 0);
922 ASSERT(pobj->ulShareCount == 1);
923
924 /* Get a free handle entry */
925 pentry = ENTRY_pentPopFreeEntry();
926 if (!pentry)
927 {
928 DPRINT1("GDIOBJ: Could not get a free entry.\n");
929 return NULL;
930 }
931
932 /* Make the object exclusively locked */
936 pobj->cExclusiveLock = 1;
939
940 /* Get object type from the hHmgr field */
941 objt = ((ULONG_PTR)pobj->hHmgr >> 16) & 0xff;
943
944 /* Check if current process is requested owner */
945 if (ulOwner == GDI_OBJ_HMGR_POWNED)
946 {
947 /* Increment the process handle count */
949
950 /* Use Process id */
952 }
953
954 /* Insert the object into the handle table */
955 pobj->hHmgr = ENTRY_hInsertObject(pentry, pobj, objt, ulOwner);
956
957 /* Return the handle */
958 DPRINT("GDIOBJ: Created handle: %p\n", pobj->hHmgr);
959 DBG_LOGEVENT(&pobj->slhLog, EVENT_CREATE_HANDLE, 0);
960 return pobj->hHmgr;
961}
962
963VOID
964NTAPI
966 POBJ pobj,
967 ULONG ulNewOwner)
968{
969 PENTRY pentry;
970 ULONG ulOldOwner;
971
972 /* This is a ugly HACK, needed to fix IntGdiSetDCOwnerEx */
973 if (GDI_HANDLE_IS_STOCKOBJ(pobj->hHmgr))
974 {
975 DPRINT("Trying to set ownership of stock object %p to %lx\n", pobj->hHmgr, ulNewOwner);
976 return;
977 }
978
979 /* Get the handle entry */
981 pentry = &gpentHmgr[GDI_HANDLE_GET_INDEX(pobj->hHmgr)];
982
983 /* Check if the new owner is the same as the old one */
984 ulOldOwner = pentry->ObjectOwner.ulObj;
985 if (ulOldOwner == ulNewOwner)
986 {
987 /* Nothing to do */
988 return;
989 }
990
991 /* Is the current process requested? */
992 if (ulNewOwner == GDI_OBJ_HMGR_POWNED)
993 {
994 /* Use process id */
995 ulNewOwner = HandleToUlong(PsGetCurrentProcessId());
996 }
997
998 // HACK
999 if (ulNewOwner == GDI_OBJ_HMGR_NONE)
1000 ulNewOwner = GDI_OBJ_HMGR_PUBLIC;
1001
1002 /* Was the object process owned? */
1003 if ((ulOldOwner != GDI_OBJ_HMGR_PUBLIC) &&
1004 (ulOldOwner != GDI_OBJ_HMGR_NONE))
1005 {
1006 /* Decrement the previous owners handle count */
1007 DecrementGdiHandleCount(ulOldOwner);
1008 }
1009
1010 /* Is the new owner a process? */
1011 if ((ulNewOwner != GDI_OBJ_HMGR_PUBLIC) &&
1012 (ulNewOwner != GDI_OBJ_HMGR_NONE))
1013 {
1014 /* Increment the new owners handle count */
1015 IncrementGdiHandleCount(ulNewOwner);
1016 }
1017 else
1018 {
1019 /* Make sure we don't leak user mode memory */
1020 NT_ASSERT(pentry->pUser == NULL);
1021 }
1022
1023 /* Set new owner */
1024 pentry->ObjectOwner.ulObj = ulNewOwner;
1025 DBG_LOGEVENT(&pobj->slhLog, EVENT_SET_OWNER, 0);
1026}
1027
1028/* Locks 2 or 3 objects at a time */
1029BOOL
1030NTAPI
1032 IN ULONG ulCount,
1033 IN HGDIOBJ* ahObj,
1034 OUT PGDIOBJ* apObj,
1035 IN UCHAR objt)
1036{
1037 UINT auiIndices[3] = {0, 1, 2};
1038 UINT i, j, tmp;
1039
1040 ASSERT(ulCount <= 3);
1041
1042 /* Sort the handles */
1043 for (i = 0; i < ulCount - 1; i++)
1044 {
1045 for (j = i + 1; j < ulCount; j++)
1046 {
1047 if ((ULONG_PTR)ahObj[auiIndices[i]] <
1048 (ULONG_PTR)ahObj[auiIndices[j]])
1049 {
1050 tmp = auiIndices[i];
1051 auiIndices[i] = auiIndices[j];
1052 auiIndices[j] = tmp;
1053 }
1054 }
1055 }
1056
1057 /* Lock the objects in safe order */
1058 for (i = 0; i < ulCount; i++)
1059 {
1060 /* Skip NULL handles */
1061 if (ahObj[auiIndices[i]] == NULL)
1062 {
1063 apObj[auiIndices[i]] = NULL;
1064 continue;
1065 }
1066
1067 /* Lock the object */
1068 apObj[auiIndices[i]] = GDIOBJ_LockObject(ahObj[auiIndices[i]], objt);
1069
1070 /* Check for failure */
1071 if (apObj[auiIndices[i]] == NULL)
1072 {
1073 /* Cleanup */
1074 while (i--)
1075 {
1076 if (apObj[auiIndices[i]])
1077 GDIOBJ_vUnlockObject(apObj[auiIndices[i]]);
1078 }
1079 return FALSE;
1080 }
1081 }
1082
1083 return TRUE;
1084}
1085
1086PVOID
1087NTAPI
1089{
1090 ULONG ulIndex = GDI_HANDLE_GET_INDEX(pobj->hHmgr);
1091 return gpentHmgr[ulIndex].pUser;
1092}
1093
1094VOID
1095NTAPI
1097{
1098 ULONG ulIndex;
1099
1100 ASSERT(pobj->hHmgr);
1101
1102 /* Get the handle index */
1103 ulIndex = GDI_HANDLE_GET_INDEX(pobj->hHmgr);
1104
1105 /* Set pointer to the usermode attribute */
1106 gpentHmgr[ulIndex].pUser = pvObjAttr;
1107}
1108
1109VOID
1110NTAPI
1112{
1113 ULONG ulIndex;
1114
1115 /* Set the object's delete flag */
1117 DBG_LOGEVENT(&pobj->slhLog, EVENT_DELETE, 0);
1118
1119 /* Get the handle index */
1120 ulIndex = GDI_HANDLE_GET_INDEX(pobj->hHmgr);
1121 if (ulIndex)
1122 {
1123 /* Reset the handle valid bit */
1125
1126 /* Check if the object is exclusively locked */
1127 if (pobj->cExclusiveLock != 0)
1128 {
1129 /* Reset lock owner and lock count */
1130 pobj->dwThreadId = 0;
1131 pobj->cExclusiveLock = 0;
1132
1133 /* Release the pushlock and reenable APCs */
1137 }
1138 }
1139
1140 /* Dereference the object (will take care of deletion) */
1142}
1143
1144BOOL
1145NTAPI
1147{
1148 PENTRY pentry;
1149
1150 pentry = ENTRY_ReferenceEntryByHandle(hobj, 0);
1151 if (!pentry) return FALSE;
1153 return TRUE;
1154}
1155
1156BOOL
1157NTAPI
1159{
1160 PENTRY pentry;
1161
1162 /* Check for stock objects */
1163 if (GDI_HANDLE_IS_STOCKOBJ(hobj))
1164 {
1165 DPRINT1("GreDeleteObject: Cannot delete stock object %p.\n", hobj);
1166 return FALSE;
1167 }
1168
1169 /* Reference the handle entry */
1170 pentry = ENTRY_ReferenceEntryByHandle(hobj, 0);
1171 if (!pentry)
1172 {
1173 DPRINT1("GreDeleteObject: Trying to delete invalid object %p\n", hobj);
1174 return FALSE;
1175 }
1176
1177 /* Check for public owner */
1178 if (pentry->ObjectOwner.ulObj == GDI_OBJ_HMGR_PUBLIC)
1179 {
1180 DPRINT1("GreDeleteObject: Trying to delete global object %p\n", hobj);
1182 return FALSE;
1183 }
1184
1185 /* Delete the object */
1187 return TRUE;
1188}
1189
1190ULONG
1191NTAPI
1193{
1194 ULONG ulIndex, ulOwner;
1195
1196 if (hobj == NULL)
1197 {
1198 DPRINT("GreGetObjectOwner: invalid NULL handle\n");
1200 }
1201
1202 /* Get the handle index */
1203 ulIndex = GDI_HANDLE_GET_INDEX(hobj);
1204
1205 /* Check if the handle is valid */
1206 if (ulIndex >= GDI_HANDLE_COUNT ||
1207 gpentHmgr[ulIndex].Objt == GDIObjType_DEF_TYPE ||
1208 ((ULONG_PTR)hobj >> 16) != gpentHmgr[ulIndex].FullUnique)
1209 {
1210 DPRINT1("GreGetObjectOwner: invalid handle 0x%p.\n", hobj);
1212 }
1213
1214 /* Get the object owner */
1215 ulOwner = gpentHmgr[ulIndex].ObjectOwner.ulObj;
1216
1217 if (ulOwner == HandleToUlong(PsGetCurrentProcessId()))
1218 return GDI_OBJ_HMGR_POWNED;
1219
1220 if (ulOwner == GDI_OBJ_HMGR_PUBLIC)
1221 return GDI_OBJ_HMGR_PUBLIC;
1222
1224}
1225
1226BOOL
1227NTAPI
1229 HGDIOBJ hobj,
1230 ULONG ulOwner,
1231 ULONG Flags)
1232{
1233 PENTRY pentry;
1234
1235 /* Check for stock objects */
1236 if (GDI_HANDLE_IS_STOCKOBJ(hobj))
1237 {
1238 DPRINT("GreSetObjectOwner: Got stock object %p\n", hobj);
1239 return FALSE;
1240 }
1241
1242 /* Reference the handle entry */
1243 pentry = ENTRY_ReferenceEntryByHandle(hobj, Flags);
1244 if (!pentry)
1245 {
1246 DPRINT("GreSetObjectOwner: Invalid handle 0x%p.\n", hobj);
1247 return FALSE;
1248 }
1249
1250 /* Call internal function */
1251 GDIOBJ_vSetObjectOwner(pentry->einfo.pobj, ulOwner);
1252
1253 /* Dereference the object */
1255
1256 return TRUE;
1257}
1258
1259BOOL
1260NTAPI
1262 HGDIOBJ hobj,
1263 ULONG ulOwner)
1264{
1265 return GreSetObjectOwnerEx(hobj, ulOwner, 0);
1266}
1267
1268INT
1269NTAPI
1271 IN HGDIOBJ hobj,
1272 IN INT cbCount,
1273 OUT PVOID pvBuffer)
1274{
1275 PVOID pvObj;
1276 UCHAR objt;
1277 INT iResult = 0;
1278
1279 /* Verify object type */
1280 objt = ((ULONG_PTR)hobj >> 16) & 0x1f;
1281 if (objt != GDIObjType_BRUSH_TYPE &&
1282 objt != GDIObjType_SURF_TYPE &&
1283 objt != GDIObjType_LFONT_TYPE &&
1284 objt != GDIObjType_PAL_TYPE)
1285 {
1286 DPRINT1("GreGetObject: Invalid object type\n");
1287 return 0;
1288 }
1289
1290 pvObj = GDIOBJ_ReferenceObjectByHandle(hobj, objt);
1291 if (!pvObj)
1292 {
1293 DPRINT("GreGetObject: Could not lock object\n");
1294 return 0;
1295 }
1296
1297 switch (GDI_HANDLE_GET_TYPE(hobj))
1298 {
1301 iResult = PEN_GetObject(pvObj, cbCount, pvBuffer);
1302 break;
1303
1305 iResult = BRUSH_GetObject(pvObj, cbCount, pvBuffer);
1306 break;
1307
1309 iResult = BITMAP_GetObject(pvObj, cbCount, pvBuffer);
1310 break;
1311
1313 iResult = FontGetObject(pvObj, cbCount, pvBuffer);
1314 break;
1315
1317 iResult = PALETTE_GetObject(pvObj, cbCount, pvBuffer);
1318 break;
1319
1320 default:
1321 DPRINT1("GDI object type of 0x%p not implemented\n", hobj);
1322 break;
1323 }
1324
1326 return iResult;
1327}
1328
1329W32KAPI
1330INT
1333 IN HANDLE hobj,
1334 IN INT cjBufferSize,
1336{
1337 UINT iResult, cjMaxSize;
1338 union
1339 {
1340 BITMAP bitmap;
1341 DIBSECTION dibsection;
1342 LOGPEN logpen;
1343 LOGBRUSH logbrush;
1344 LOGFONTW logfontw;
1345 EXTLOGFONTW extlogfontw;
1346 ENUMLOGFONTEXDVW enumlogfontexdvw;
1347 } object;
1348
1349 /* Normalize to the largest supported object size */
1350 cjMaxSize = min((UINT)cjBufferSize, sizeof(object));
1351
1352 /* Now do the actual call */
1353 iResult = GreGetObject(hobj, cjMaxSize, lpBuffer ? &object : NULL);
1354
1355 /* Check if we have a buffer and data */
1356 if ((lpBuffer != NULL) && (iResult != 0))
1357 {
1358 /* Enter SEH for buffer transfer */
1359 _SEH2_TRY
1360 {
1361 /* Probe the buffer and copy it */
1362 cjMaxSize = min(cjMaxSize, iResult);
1363 ProbeForWrite(lpBuffer, cjMaxSize, sizeof(WORD));
1364 RtlCopyMemory(lpBuffer, &object, cjMaxSize);
1365 }
1367 {
1368 /* Clear the return value.
1369 * Do *NOT* set last error here! */
1370 iResult = 0;
1371 }
1372 _SEH2_END;
1373 }
1374
1375 /* Return the count */
1376 return iResult;
1377}
1378
1379W32KAPI
1380HANDLE
1383 IN ULONG ulType)
1384{
1385 POBJ pObject;
1386 HANDLE handle;
1387
1388 /* Check if ulType is valid */
1392 {
1393 DPRINT1("NtGdiCreateClientObj: Invalid object type 0x%lx.\n", ulType);
1394 return NULL;
1395 }
1396
1397 /* Allocate a new object */
1399 sizeof(CLIENTOBJ),
1401 if (!pObject)
1402 {
1403 DPRINT1("NtGdiCreateClientObj: Could not allocate a clientobj.\n");
1404 return NULL;
1405 }
1406
1407 /* Set the real object type */
1409
1410 /* Create a handle */
1412 if (!handle)
1413 {
1414 DPRINT1("NtGdiCreateClientObj: Could not create a handle.\n");
1416 return NULL;
1417 }
1418
1419 /* Unlock it */
1421
1422 return handle;
1423}
1424
1425W32KAPI
1426BOOL
1429 IN HANDLE hobj)
1430{
1431 /* We first need to get the real type from the handle */
1433
1434 /* Check if it's really a CLIENTOBJ */
1436 {
1437 /* FIXME: SetLastError? */
1438 return FALSE;
1439 }
1440
1441 return GreDeleteObject(hobj);
1442}
1443
1444
1445
1447
1450{
1451 if (ExpectedType == GDI_OBJECT_TYPE_DONTCARE)
1452 ExpectedType = GDI_HANDLE_GET_TYPE(hObj);
1453 return GDIOBJ_ReferenceObjectByHandle(hObj, (ExpectedType >> 16) & 0x1f);
1454}
1455
1456// This function is not safe to use with concurrent deleting attempts
1457// That shouldn't be a problem, since we don't have any processes yet,
1458// that could delete the handle
1459BOOL
1460NTAPI
1462{
1463 PENTRY pentry;
1464 POBJ pobj;
1465
1466 /* Reference the handle entry */
1467 pentry = ENTRY_ReferenceEntryByHandle(*phObj, 0);
1468 if (!pentry)
1469 {
1470 DPRINT1("GDIOBJ: Requested handle 0x%p is not valid.\n", *phObj);
1471 return FALSE;
1472 }
1473
1474 /* Update the entry */
1476 pentry->ObjectOwner.ulObj = 0;
1477
1478 /* Get the pointer to the BASEOBJECT */
1479 pobj = pentry->einfo.pobj;
1480
1481 /* Calculate the new handle */
1483
1484 /* Return the new handle */
1485 *phObj = pobj->hHmgr;
1486
1487 /* Dereference the handle */
1489
1490 return TRUE;
1491}
1492
1493BOOL
1494NTAPI
1496{
1497 PENTRY pentry;
1498 POBJ pobj;
1499
1500 /* Reference the handle entry */
1501 pentry = ENTRY_ReferenceEntryByHandle(*phObj, 0);
1502 if (!pentry)
1503 {
1504 DPRINT1("GDIOBJ: Requested handle 0x%p is not valid.\n", *phObj);
1505 return FALSE;
1506 }
1507
1508 /* Update the entry */
1509 pentry->FullUnique &= ~GDI_ENTRY_STOCK_MASK;
1511
1512 /* Get the pointer to the BASEOBJECT */
1513 pobj = pentry->einfo.pobj;
1514
1515 /* Calculate the new handle */
1516 pobj->hHmgr = (HGDIOBJ)((ULONG_PTR)pobj->hHmgr & ~GDI_HANDLE_STOCK_MASK);
1517
1518 /* Return the new handle */
1519 *phObj = pobj->hHmgr;
1520
1521 /* Dereference the handle */
1523
1524 return TRUE;
1525}
1526
1527POBJ NTAPI
1529{
1530 POBJ pobj;
1531 FLONG fl = 0;
1532 UCHAR objt = (ObjectType >> 16) & 0xFF;
1533
1534 if ((objt == GDIObjType_DC_TYPE && cjSize == sizeof(DC)) ||
1535 (objt == GDIObjType_PAL_TYPE && cjSize == sizeof(PALETTE)) ||
1536 (objt == GDIObjType_RGN_TYPE && cjSize == sizeof(REGION)) ||
1537 (objt == GDIObjType_SURF_TYPE && cjSize == sizeof(SURFACE)) ||
1538 (objt == GDIObjType_PATH_TYPE && cjSize == sizeof(PATH)))
1539 {
1541 }
1542
1543 pobj = GDIOBJ_AllocateObject(objt, cjSize, fl);
1544 if (!pobj)
1545 {
1546 return NULL;
1547 }
1548
1550 {
1551 GDIOBJ_vFreeObject(pobj);
1552 return NULL;
1553 }
1554 return pobj;
1555}
1556
1559{
1560 PVOID pvMappedView = NULL;
1562 LARGE_INTEGER liOffset;
1563 SIZE_T cjViewSize = sizeof(GDI_HANDLE_TABLE);
1564
1565 liOffset.QuadPart = 0;
1566
1568 ASSERT(pProcess != NULL);
1569
1571 pProcess,
1572 &pvMappedView,
1573 0,
1574 0,
1575 &liOffset,
1576 &cjViewSize,
1577 ViewUnmap,
1580
1581 if (!NT_SUCCESS(Status))
1582 return NULL;
1583
1584 return pvMappedView;
1585}
1586
1587BOOL NTAPI
1589{
1590 PENTRY pentry;
1591 ULONG ulIndex;
1592 DWORD dwProcessId;
1593 PPROCESSINFO ppi;
1594
1595 DPRINT("CleanupForProcess prochandle %p Pid %p\n",
1596 Process, Process->UniqueProcessId);
1597
1599
1600 /* Get the current process Id */
1601 dwProcessId = PtrToUlong(PsGetCurrentProcessId());
1602
1603 /* Loop all handles in the handle table */
1604 for (ulIndex = RESERVE_ENTRIES_COUNT; ulIndex < gulFirstUnused; ulIndex++)
1605 {
1606 pentry = &gpentHmgr[ulIndex];
1607
1608 /* Check if the object is owned by the process */
1609 if (pentry->ObjectOwner.ulObj == dwProcessId)
1610 {
1611 ASSERT(pentry->einfo.pobj->cExclusiveLock == 0);
1612
1613 /* Reference the object and delete it */
1616 }
1617 }
1618
1619#if DBG
1621#endif
1622
1624 DPRINT("Completed cleanup for process %p\n", Process->UniqueProcessId);
1625 if (ppi->GDIHandleCount != 0)
1626 {
1627 DPRINT1("Leaking %d handles!\n", ppi->GDIHandleCount);
1628 ASSERT(FALSE);
1629 }
1630
1631 /* Loop all handles in the handle table */
1632 for (ulIndex = RESERVE_ENTRIES_COUNT; ulIndex < gulFirstUnused; ulIndex++)
1633 {
1634 pentry = &gpentHmgr[ulIndex];
1635
1636 /* Check if the object is owned by the process */
1637 if (pentry->ObjectOwner.ulObj == dwProcessId)
1638 {
1639 DPRINT1("Leaking object. Index=%lx, type=0x%x, refcount=%lx\n",
1640 ulIndex, pentry->Objt, gpaulRefCount[ulIndex]);
1641 DBG_DUMP_EVENT_LIST(&pentry->einfo.pobj->slhLog);
1642 //DBG_CLEANUP_EVENT_LIST(&pentry->einfo.pobj->slhLog);
1643 ASSERT(FALSE);
1644 }
1645 }
1646
1647 return TRUE;
1648}
1649
1653{
1654 PPROCESSINFO ppi;
1655
1657 NT_ASSERT(ppi != NULL);
1658
1659 return ppi->pPoolBrushAttr;
1660}
1661
1662/* EOF */
NTSTATUS NTAPI MmMapViewInSessionSpace(IN PVOID Section, OUT PVOID *MappedBase, IN OUT PSIZE_T ViewSize)
Definition: section.c:2687
#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:97
#define HandleToUlong(h)
Definition: basetsd.h:79
#define ULongToHandle(h)
Definition: basetsd.h:81
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
static TAGREF LPCWSTR LPDWORD LPVOID lpBuffer
Definition: db.cpp:175
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 int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
unsigned short WORD
Definition: ntddk_ex.h:93
_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 EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:90
#define InterlockedExchangeAdd
Definition: interlocked.h:181
#define InterlockedOr
Definition: interlocked.h:224
#define InterlockedCompareExchange
Definition: interlocked.h:104
#define InterlockedOr16
Definition: interlocked.h:239
#define InterlockedAnd
Definition: interlocked.h:62
#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
#define _In_
Definition: no_sal2.h:158
#define _Interlocked_operand_
Definition: no_sal2.h:410
#define PAGE_READWRITE
Definition: nt_native.h:1304
#define SECTION_ALL_ACCESS
Definition: nt_native.h:1293
@ ViewUnmap
Definition: nt_native.h:1279
unsigned long FLONG
Definition: ntbasedef.h:374
#define DBG_UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:326
#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
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:66
#define _SEH2_END
Definition: pseh2_64.h:155
#define _SEH2_TRY
Definition: pseh2_64.h:55
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:4001
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:4625
#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
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(PTEXTOBJ plfont, ULONG cjBuffer, PVOID pvBuffer)
Definition: font.c:293
BOOL NTAPI GreSetObjectOwner(HGDIOBJ hobj, ULONG ulOwner)
Definition: gdiobj.c:1261
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
static PENTRY ENTRY_pentPopFreeEntry(VOID)
Definition: gdiobj.c:382
BOOL NTAPI GDIOBJ_ConvertToStockObj(HGDIOBJ *phObj)
Definition: gdiobj.c:1461
POBJ NTAPI GDIOBJ_ReferenceObjectByHandle(HGDIOBJ hobj, UCHAR objt)
Definition: gdiobj.c:691
VOID NTAPI GDIOBJ_vDereferenceObject(POBJ pobj)
Definition: gdiobj.c:631
PVOID NTAPI GDIOBJ_pvGetObjectAttr(POBJ pobj)
Definition: gdiobj.c:1088
static PVOID gpvGdiHdlTblSection
Definition: gdiobj.c:148
BOOL NTAPI GreSetObjectOwnerEx(HGDIOBJ hobj, ULONG ulOwner, ULONG Flags)
Definition: gdiobj.c:1228
BOOL NTAPI GDIOBJ_ConvertFromStockObj(HGDIOBJ *phObj)
Definition: gdiobj.c:1495
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:596
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:1332
FORCEINLINE void INCREASE_THREAD_LOCK_COUNT(_In_ HANDLE hobj)
Definition: gdiobj.c:63
W32KAPI BOOL APIENTRY NtGdiDeleteClientObj(IN HANDLE hobj)
Definition: gdiobj.c:1428
HGDIOBJ NTAPI GDIOBJ_hInsertObject(POBJ pobj, ULONG ulOwner)
Definition: gdiobj.c:912
VOID NTAPI GDIOBJ_vSetObjectAttr(POBJ pobj, PVOID pvObjAttr)
Definition: gdiobj.c:1096
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:539
static VOID DecrementGdiHandleCount(ULONG ulProcessId)
Definition: gdiobj.c:365
BOOL NTAPI GreDeleteObject(HGDIOBJ hobj)
Definition: gdiobj.c:1158
BOOL NTAPI GDIOBJ_bLockMultipleObjects(IN ULONG ulCount, IN HGDIOBJ *ahObj, OUT PGDIOBJ *apObj, IN UCHAR objt)
Definition: gdiobj.c:1031
BOOL NTAPI GDI_CleanupForProcess(struct _EPROCESS *Process)
Definition: gdiobj.c:1588
VOID NTAPI GDIOBJ_vSetObjectOwner(POBJ pobj, ULONG ulNewOwner)
Definition: gdiobj.c:965
#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:826
ULONG NTAPI GreGetObjectOwner(HGDIOBJ hobj)
Definition: gdiobj.c:1192
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:562
BOOL NTAPI GreIsHandleValid(HGDIOBJ hobj)
Definition: gdiobj.c:1146
PVOID NTAPI GDI_MapHandleTable(PEPROCESS pProcess)
Definition: gdiobj.c:1558
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:1528
PGDIOBJ NTAPI GDIOBJ_ShareLockObj(HGDIOBJ hObj, DWORD ExpectedType)
Definition: gdiobj.c:1449
W32KAPI HANDLE APIENTRY NtGdiCreateClientObj(IN ULONG ulType)
Definition: gdiobj.c:1382
INT NTAPI GreGetObject(IN HGDIOBJ hobj, IN INT cbCount, OUT PVOID pvBuffer)
Definition: gdiobj.c:1270
#define ASSERT_TRYLOCK_OBJECT_TYPE(objt)
Definition: gdiobj.c:127
VOID NTAPI GDIOBJ_vUnlockObject(POBJ pobj)
Definition: gdiobj.c:880
PGDI_HANDLE_TABLE GdiHandleTable
Definition: gdiobj.c:1446
VOID NTAPI GDIOBJ_vDeleteObject(POBJ pobj)
Definition: gdiobj.c:1111
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:757
static PENTRY ENTRY_ReferenceEntryByHandle(HGDIOBJ hobj, FLONG fl)
Definition: gdiobj.c:478
VOID NTAPI GDIOBJ_vReferenceObjectByPointer(POBJ pobj)
Definition: gdiobj.c:734
@ 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
FORCEINLINE BOOLEAN ExTryAcquirePushLockExclusive(PEX_PUSH_LOCK PushLock)
Definition: misc.h:104
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:252
_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