ReactOS 0.4.15-dev-8093-g3285f69
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 /* Get the handle index */
1197 ulIndex = GDI_HANDLE_GET_INDEX(hobj);
1198
1199 /* Check if the handle is valid */
1200 if (ulIndex >= GDI_HANDLE_COUNT ||
1201 gpentHmgr[ulIndex].Objt == GDIObjType_DEF_TYPE ||
1202 ((ULONG_PTR)hobj >> 16) != gpentHmgr[ulIndex].FullUnique)
1203 {
1204 DPRINT1("GreGetObjectOwner: invalid handle 0x%p.\n", hobj);
1206 }
1207
1208 /* Get the object owner */
1209 ulOwner = gpentHmgr[ulIndex].ObjectOwner.ulObj;
1210
1211 if (ulOwner == HandleToUlong(PsGetCurrentProcessId()))
1212 return GDI_OBJ_HMGR_POWNED;
1213
1214 if (ulOwner == GDI_OBJ_HMGR_PUBLIC)
1215 return GDI_OBJ_HMGR_PUBLIC;
1216
1218}
1219
1220BOOL
1221NTAPI
1223 HGDIOBJ hobj,
1224 ULONG ulOwner,
1225 ULONG Flags)
1226{
1227 PENTRY pentry;
1228
1229 /* Check for stock objects */
1230 if (GDI_HANDLE_IS_STOCKOBJ(hobj))
1231 {
1232 DPRINT("GreSetObjectOwner: Got stock object %p\n", hobj);
1233 return FALSE;
1234 }
1235
1236 /* Reference the handle entry */
1237 pentry = ENTRY_ReferenceEntryByHandle(hobj, Flags);
1238 if (!pentry)
1239 {
1240 DPRINT("GreSetObjectOwner: Invalid handle 0x%p.\n", hobj);
1241 return FALSE;
1242 }
1243
1244 /* Call internal function */
1245 GDIOBJ_vSetObjectOwner(pentry->einfo.pobj, ulOwner);
1246
1247 /* Dereference the object */
1249
1250 return TRUE;
1251}
1252
1253BOOL
1254NTAPI
1256 HGDIOBJ hobj,
1257 ULONG ulOwner)
1258{
1259 return GreSetObjectOwnerEx(hobj, ulOwner, 0);
1260}
1261
1262INT
1263NTAPI
1265 IN HGDIOBJ hobj,
1266 IN INT cbCount,
1267 OUT PVOID pvBuffer)
1268{
1269 PVOID pvObj;
1270 UCHAR objt;
1271 INT iResult = 0;
1272
1273 /* Verify object type */
1274 objt = ((ULONG_PTR)hobj >> 16) & 0x1f;
1275 if (objt != GDIObjType_BRUSH_TYPE &&
1276 objt != GDIObjType_SURF_TYPE &&
1277 objt != GDIObjType_LFONT_TYPE &&
1278 objt != GDIObjType_PAL_TYPE)
1279 {
1280 DPRINT1("GreGetObject: Invalid object type\n");
1281 return 0;
1282 }
1283
1284 pvObj = GDIOBJ_ReferenceObjectByHandle(hobj, objt);
1285 if (!pvObj)
1286 {
1287 DPRINT("GreGetObject: Could not lock object\n");
1288 return 0;
1289 }
1290
1291 switch (GDI_HANDLE_GET_TYPE(hobj))
1292 {
1295 iResult = PEN_GetObject(pvObj, cbCount, pvBuffer);
1296 break;
1297
1299 iResult = BRUSH_GetObject(pvObj, cbCount, pvBuffer);
1300 break;
1301
1303 iResult = BITMAP_GetObject(pvObj, cbCount, pvBuffer);
1304 break;
1305
1307 iResult = FontGetObject(pvObj, cbCount, pvBuffer);
1308 break;
1309
1311 iResult = PALETTE_GetObject(pvObj, cbCount, pvBuffer);
1312 break;
1313
1314 default:
1315 DPRINT1("GDI object type of 0x%p not implemented\n", hobj);
1316 break;
1317 }
1318
1320 return iResult;
1321}
1322
1323W32KAPI
1324INT
1327 IN HANDLE hobj,
1328 IN INT cjBufferSize,
1330{
1331 UINT iResult, cjMaxSize;
1332 union
1333 {
1334 BITMAP bitmap;
1335 DIBSECTION dibsection;
1336 LOGPEN logpen;
1337 LOGBRUSH logbrush;
1338 LOGFONTW logfontw;
1339 EXTLOGFONTW extlogfontw;
1340 ENUMLOGFONTEXDVW enumlogfontexdvw;
1341 } object;
1342
1343 /* Normalize to the largest supported object size */
1344 cjMaxSize = min((UINT)cjBufferSize, sizeof(object));
1345
1346 /* Now do the actual call */
1347 iResult = GreGetObject(hobj, cjMaxSize, lpBuffer ? &object : NULL);
1348
1349 /* Check if we have a buffer and data */
1350 if ((lpBuffer != NULL) && (iResult != 0))
1351 {
1352 /* Enter SEH for buffer transfer */
1353 _SEH2_TRY
1354 {
1355 /* Probe the buffer and copy it */
1356 cjMaxSize = min(cjMaxSize, iResult);
1357 ProbeForWrite(lpBuffer, cjMaxSize, sizeof(WORD));
1358 RtlCopyMemory(lpBuffer, &object, cjMaxSize);
1359 }
1361 {
1362 /* Clear the return value.
1363 * Do *NOT* set last error here! */
1364 iResult = 0;
1365 }
1366 _SEH2_END;
1367 }
1368
1369 /* Return the count */
1370 return iResult;
1371}
1372
1373W32KAPI
1374HANDLE
1377 IN ULONG ulType)
1378{
1379 POBJ pObject;
1380 HANDLE handle;
1381
1382 /* Check if ulType is valid */
1386 {
1387 DPRINT1("NtGdiCreateClientObj: Invalid object type 0x%lx.\n", ulType);
1388 return NULL;
1389 }
1390
1391 /* Allocate a new object */
1393 sizeof(CLIENTOBJ),
1395 if (!pObject)
1396 {
1397 DPRINT1("NtGdiCreateClientObj: Could not allocate a clientobj.\n");
1398 return NULL;
1399 }
1400
1401 /* Set the real object type */
1403
1404 /* Create a handle */
1406 if (!handle)
1407 {
1408 DPRINT1("NtGdiCreateClientObj: Could not create a handle.\n");
1410 return NULL;
1411 }
1412
1413 /* Unlock it */
1415
1416 return handle;
1417}
1418
1419W32KAPI
1420BOOL
1423 IN HANDLE hobj)
1424{
1425 /* We first need to get the real type from the handle */
1427
1428 /* Check if it's really a CLIENTOBJ */
1430 {
1431 /* FIXME: SetLastError? */
1432 return FALSE;
1433 }
1434
1435 return GreDeleteObject(hobj);
1436}
1437
1438
1439
1441
1444{
1445 if (ExpectedType == GDI_OBJECT_TYPE_DONTCARE)
1446 ExpectedType = GDI_HANDLE_GET_TYPE(hObj);
1447 return GDIOBJ_ReferenceObjectByHandle(hObj, (ExpectedType >> 16) & 0x1f);
1448}
1449
1450// This function is not safe to use with concurrent deleting attempts
1451// That shouldn't be a problem, since we don't have any processes yet,
1452// that could delete the handle
1453BOOL
1454NTAPI
1456{
1457 PENTRY pentry;
1458 POBJ pobj;
1459
1460 /* Reference the handle entry */
1461 pentry = ENTRY_ReferenceEntryByHandle(*phObj, 0);
1462 if (!pentry)
1463 {
1464 DPRINT1("GDIOBJ: Requested handle 0x%p is not valid.\n", *phObj);
1465 return FALSE;
1466 }
1467
1468 /* Update the entry */
1470 pentry->ObjectOwner.ulObj = 0;
1471
1472 /* Get the pointer to the BASEOBJECT */
1473 pobj = pentry->einfo.pobj;
1474
1475 /* Calculate the new handle */
1477
1478 /* Return the new handle */
1479 *phObj = pobj->hHmgr;
1480
1481 /* Dereference the handle */
1483
1484 return TRUE;
1485}
1486
1487BOOL
1488NTAPI
1490{
1491 PENTRY pentry;
1492 POBJ pobj;
1493
1494 /* Reference the handle entry */
1495 pentry = ENTRY_ReferenceEntryByHandle(*phObj, 0);
1496 if (!pentry)
1497 {
1498 DPRINT1("GDIOBJ: Requested handle 0x%p is not valid.\n", *phObj);
1499 return FALSE;
1500 }
1501
1502 /* Update the entry */
1503 pentry->FullUnique &= ~GDI_ENTRY_STOCK_MASK;
1505
1506 /* Get the pointer to the BASEOBJECT */
1507 pobj = pentry->einfo.pobj;
1508
1509 /* Calculate the new handle */
1510 pobj->hHmgr = (HGDIOBJ)((ULONG_PTR)pobj->hHmgr & ~GDI_HANDLE_STOCK_MASK);
1511
1512 /* Return the new handle */
1513 *phObj = pobj->hHmgr;
1514
1515 /* Dereference the handle */
1517
1518 return TRUE;
1519}
1520
1521POBJ NTAPI
1523{
1524 POBJ pobj;
1525 FLONG fl = 0;
1526 UCHAR objt = (ObjectType >> 16) & 0xFF;
1527
1528 if ((objt == GDIObjType_DC_TYPE && cjSize == sizeof(DC)) ||
1529 (objt == GDIObjType_PAL_TYPE && cjSize == sizeof(PALETTE)) ||
1530 (objt == GDIObjType_RGN_TYPE && cjSize == sizeof(REGION)) ||
1531 (objt == GDIObjType_SURF_TYPE && cjSize == sizeof(SURFACE)) ||
1532 (objt == GDIObjType_PATH_TYPE && cjSize == sizeof(PATH)))
1533 {
1535 }
1536
1537 pobj = GDIOBJ_AllocateObject(objt, cjSize, fl);
1538 if (!pobj)
1539 {
1540 return NULL;
1541 }
1542
1544 {
1545 GDIOBJ_vFreeObject(pobj);
1546 return NULL;
1547 }
1548 return pobj;
1549}
1550
1553{
1554 PVOID pvMappedView = NULL;
1556 LARGE_INTEGER liOffset;
1557 SIZE_T cjViewSize = sizeof(GDI_HANDLE_TABLE);
1558
1559 liOffset.QuadPart = 0;
1560
1562 ASSERT(pProcess != NULL);
1563
1565 pProcess,
1566 &pvMappedView,
1567 0,
1568 0,
1569 &liOffset,
1570 &cjViewSize,
1571 ViewUnmap,
1574
1575 if (!NT_SUCCESS(Status))
1576 return NULL;
1577
1578 return pvMappedView;
1579}
1580
1581BOOL NTAPI
1583{
1584 PENTRY pentry;
1585 ULONG ulIndex;
1586 DWORD dwProcessId;
1587 PPROCESSINFO ppi;
1588
1589 DPRINT("CleanupForProcess prochandle %p Pid %p\n",
1590 Process, Process->UniqueProcessId);
1591
1593
1594 /* Get the current process Id */
1595 dwProcessId = PtrToUlong(PsGetCurrentProcessId());
1596
1597 /* Loop all handles in the handle table */
1598 for (ulIndex = RESERVE_ENTRIES_COUNT; ulIndex < gulFirstUnused; ulIndex++)
1599 {
1600 pentry = &gpentHmgr[ulIndex];
1601
1602 /* Check if the object is owned by the process */
1603 if (pentry->ObjectOwner.ulObj == dwProcessId)
1604 {
1605 ASSERT(pentry->einfo.pobj->cExclusiveLock == 0);
1606
1607 /* Reference the object and delete it */
1610 }
1611 }
1612
1613#if DBG
1615#endif
1616
1618 DPRINT("Completed cleanup for process %p\n", Process->UniqueProcessId);
1619 if (ppi->GDIHandleCount != 0)
1620 {
1621 DPRINT1("Leaking %d handles!\n", ppi->GDIHandleCount);
1622 ASSERT(FALSE);
1623 }
1624
1625 /* Loop all handles in the handle table */
1626 for (ulIndex = RESERVE_ENTRIES_COUNT; ulIndex < gulFirstUnused; ulIndex++)
1627 {
1628 pentry = &gpentHmgr[ulIndex];
1629
1630 /* Check if the object is owned by the process */
1631 if (pentry->ObjectOwner.ulObj == dwProcessId)
1632 {
1633 DPRINT1("Leaking object. Index=%lx, type=0x%x, refcount=%lx\n",
1634 ulIndex, pentry->Objt, gpaulRefCount[ulIndex]);
1635 DBG_DUMP_EVENT_LIST(&pentry->einfo.pobj->slhLog);
1636 //DBG_CLEANUP_EVENT_LIST(&pentry->einfo.pobj->slhLog);
1637 ASSERT(FALSE);
1638 }
1639 }
1640
1641 return TRUE;
1642}
1643
1647{
1648 PPROCESSINFO ppi;
1649
1651 NT_ASSERT(ppi != NULL);
1652
1653 return ppi->pPoolBrushAttr;
1654}
1655
1656/* EOF */
NTSTATUS NTAPI MmMapViewInSessionSpace(IN PVOID Section, OUT PVOID *MappedBase, IN OUT PSIZE_T ViewSize)
Definition: section.c:3054
#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
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:32
#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:1013
FORCEINLINE VOID ExAcquirePushLockExclusive(PEX_PUSH_LOCK PushLock)
Definition: ex.h:1036
FORCEINLINE VOID ExReleasePushLockExclusive(PEX_PUSH_LOCK PushLock)
Definition: ex.h:1252
VOID NTAPI ProbeForWrite(IN PVOID Address, IN SIZE_T Length, IN ULONG Alignment)
Definition: exintrin.c:143
DWORD dwThreadId
Definition: fdebug.c:31
#define _SEH2_END
Definition: filesup.c:22
#define _SEH2_TRY
Definition: filesup.c:19
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:85
#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
#define _In_
Definition: ms_sal.h:308
#define _Interlocked_operand_
Definition: ms_sal.h:2951
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 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:366
#define DBG_UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:318
#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
#define STATUS_NO_MEMORY
Definition: ntstatus.h:260
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
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:3996
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:4620
#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:292
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:1255
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:1455
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:1222
BOOL NTAPI GDIOBJ_ConvertFromStockObj(HGDIOBJ *phObj)
Definition: gdiobj.c:1489
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:1326
FORCEINLINE void INCREASE_THREAD_LOCK_COUNT(_In_ HANDLE hobj)
Definition: gdiobj.c:63
W32KAPI BOOL APIENTRY NtGdiDeleteClientObj(IN HANDLE hobj)
Definition: gdiobj.c:1422
@ 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
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:1582
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:1552
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:1522
PGDIOBJ NTAPI GDIOBJ_ShareLockObj(HGDIOBJ hObj, DWORD ExpectedType)
Definition: gdiobj.c:1443
W32KAPI HANDLE APIENTRY NtGdiCreateClientObj(IN ULONG ulType)
Definition: gdiobj.c:1376
INT NTAPI GreGetObject(IN HGDIOBJ hobj, IN INT cbCount, OUT PVOID pvBuffer)
Definition: gdiobj.c:1264
#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:1440
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
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:3310
unsigned char UCHAR
Definition: xmlstorage.h:181