2 * ReactOS W32 Subsystem
3 * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 * GDIOBJ.C - GDI object manipulation routines
22 * $Id: gdiobj.c,v 1.50 2003/11/19 12:25:03 weiden Exp $
26 #undef WIN32_LEAN_AND_MEAN
27 #define WIN32_NO_STATUS
29 #include <ddk/ntddk.h>
30 #include <include/dce.h>
31 #include <include/object.h>
32 #include <win32k/gdiobj.h>
33 #include <win32k/brush.h>
34 #include <win32k/pen.h>
35 #include <win32k/text.h>
36 #include <win32k/dc.h>
37 #include <win32k/bitmaps.h>
38 #include <win32k/region.h>
39 #include <win32k/cursoricon.h>
40 #include <include/palette.h>
42 #include <win32k/debug1.h>
44 /*! Size of the GDI handle table
45 * http://www.windevnet.com/documents/s=7290/wdj9902b/9902b.htm
46 * gdi handle table can hold 0x4000 handles
48 #define GDI_HANDLE_COUNT 0x4000
50 #define GDI_GLOBAL_PROCESS ((HANDLE) 0xffffffff)
52 #define GDI_HANDLE_INDEX_MASK (GDI_HANDLE_COUNT - 1)
53 #define GDI_HANDLE_TYPE_MASK 0x007f0000
54 #define GDI_HANDLE_STOCK_MASK 0x00800000
56 #define GDI_HANDLE_CREATE(i, t) ((HANDLE)(((i) & GDI_HANDLE_INDEX_MASK) | ((t) & GDI_HANDLE_TYPE_MASK)))
57 #define GDI_HANDLE_GET_INDEX(h) (((DWORD)(h)) & GDI_HANDLE_INDEX_MASK)
58 #define GDI_HANDLE_GET_TYPE(h) (((DWORD)(h)) & GDI_HANDLE_TYPE_MASK)
59 #define GDI_HANDLE_IS_TYPE(h, t) ((t) == (((DWORD)(h)) & GDI_HANDLE_TYPE_MASK))
60 #define GDI_HANDLE_IS_STOCKOBJ(h) (0 != (((DWORD)(h)) & GDI_HANDLE_STOCK_MASK))
61 #define GDI_HANDLE_SET_STOCKOBJ(h) ((h) = (HANDLE)(((DWORD)(h)) | GDI_HANDLE_STOCK_MASK))
63 #define GDI_TYPE_TO_MAGIC(t) ((WORD) ((t) >> 16))
64 #define GDI_MAGIC_TO_TYPE(m) ((DWORD)(m) << 16)
66 /* FIXME Ownership of GDI objects by processes not properly implemented yet */
68 #define GDI_VALID_OBJECT(h, obj, t, f) \
70 && (GDI_MAGIC_TO_TYPE((obj)->Magic) == (t) || GDI_OBJECT_TYPE_DONTCARE == (t)) \
71 && (GDI_HANDLE_GET_TYPE((h)) == GDI_MAGIC_TO_TYPE((obj)->Magic)) \
72 && (((obj)->hProcessId == PsGetCurrentProcessId()) \
73 || (GDI_GLOBAL_PROCESS == (obj)->hProcessId) \
74 || ((f) & GDIOBJFLAG_IGNOREPID)))
76 #define GDI_VALID_OBJECT(h, obj, t, f) \
78 && (GDI_MAGIC_TO_TYPE((obj)->Magic) == (t) || GDI_OBJECT_TYPE_DONTCARE == (t)) \
79 && (GDI_HANDLE_GET_TYPE((h)) == GDI_MAGIC_TO_TYPE((obj)->Magic)))
82 typedef struct _GDI_HANDLE_TABLE
85 PGDIOBJHDR Handles
[1];
86 } GDI_HANDLE_TABLE
, *PGDI_HANDLE_TABLE
;
88 /* GDI stock objects */
90 static LOGBRUSH WhiteBrush
=
91 { BS_SOLID
, RGB(255,255,255), 0 };
93 static LOGBRUSH LtGrayBrush
=
94 /* FIXME : this should perhaps be BS_HATCHED, at least for 1 bitperpixel */
95 { BS_SOLID
, RGB(192,192,192), 0 };
97 static LOGBRUSH GrayBrush
=
98 /* FIXME : this should perhaps be BS_HATCHED, at least for 1 bitperpixel */
99 { BS_SOLID
, RGB(128,128,128), 0 };
101 static LOGBRUSH DkGrayBrush
=
102 /* This is BS_HATCHED, for 1 bitperpixel. This makes the spray work in pbrush */
103 /* NB_HATCH_STYLES is an index into HatchBrushes */
104 { BS_HATCHED
, RGB(0,0,0), NB_HATCH_STYLES
};
106 static LOGBRUSH BlackBrush
=
107 { BS_SOLID
, RGB(0,0,0), 0 };
109 static LOGBRUSH NullBrush
=
112 static LOGPEN WhitePen
=
113 { PS_SOLID
, { 0, 0 }, RGB(255,255,255) };
115 static LOGPEN BlackPen
=
116 { PS_SOLID
, { 0, 0 }, RGB(0,0,0) };
118 static LOGPEN NullPen
=
119 { PS_NULL
, { 0, 0 }, 0 };
121 static LOGFONTW OEMFixedFont
=
122 { 14, 0, 0, 0, FW_NORMAL
, FALSE
, FALSE
, FALSE
, OEM_CHARSET
,
123 0, 0, DEFAULT_QUALITY
, FIXED_PITCH
| FF_MODERN
, L
"" };
125 static LOGFONTW AnsiFixedFont
=
126 { 14, 0, 0, 0, FW_NORMAL
, FALSE
, FALSE
, FALSE
, ANSI_CHARSET
,
127 0, 0, DEFAULT_QUALITY
, FIXED_PITCH
| FF_MODERN
, L
"" };
129 /*static LOGFONTW AnsiVarFont =
130 *{ 14, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
131 * 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS, L"MS Sans Serif" }; */
133 static LOGFONTW SystemFont
=
134 { 14, 0, 0, 0, FW_NORMAL
, FALSE
, FALSE
, FALSE
, ANSI_CHARSET
,
135 0, 0, DEFAULT_QUALITY
, VARIABLE_PITCH
| FF_SWISS
, L
"System" };
137 static LOGFONTW DeviceDefaultFont
=
138 { 14, 0, 0, 0, FW_NORMAL
, FALSE
, FALSE
, FALSE
, ANSI_CHARSET
,
139 0, 0, DEFAULT_QUALITY
, VARIABLE_PITCH
| FF_SWISS
, L
"" };
141 static LOGFONTW SystemFixedFont
=
142 { 14, 0, 0, 0, FW_NORMAL
, FALSE
, FALSE
, FALSE
, ANSI_CHARSET
,
143 0, 0, DEFAULT_QUALITY
, FIXED_PITCH
| FF_MODERN
, L
"" };
145 /* FIXME: Is this correct? */
146 static LOGFONTW DefaultGuiFont
=
147 { 14, 0, 0, 0, FW_NORMAL
, FALSE
, FALSE
, FALSE
, ANSI_CHARSET
,
148 0, 0, DEFAULT_QUALITY
, VARIABLE_PITCH
| FF_SWISS
, L
"MS Sans Serif" };
150 #define NB_STOCK_OBJECTS (DEFAULT_GUI_FONT + 1)
152 static HGDIOBJ
*StockObjects
[NB_STOCK_OBJECTS
];
153 static PGDI_HANDLE_TABLE HandleTable
= 0;
154 static FAST_MUTEX HandleTableMutex
;
155 static FAST_MUTEX RefCountHandling
;
158 * Allocate GDI object table.
159 * \param Size - number of entries in the object table.
160 * Notes:: Must be called at IRQL < DISPATCH_LEVEL.
162 static PGDI_HANDLE_TABLE FASTCALL
163 GDIOBJ_iAllocHandleTable (WORD Size
)
165 PGDI_HANDLE_TABLE handleTable
;
167 /* prevent APC delivery for the *FastMutexUnsafe calls */
168 const KIRQL PrevIrql
= KfRaiseIrql(APC_LEVEL
);
169 ExAcquireFastMutexUnsafe (&HandleTableMutex
);
170 handleTable
= ExAllocatePool(PagedPool
,
171 sizeof(GDI_HANDLE_TABLE
) +
172 sizeof(PGDIOBJ
) * Size
);
173 ASSERT( handleTable
);
176 sizeof(GDI_HANDLE_TABLE
) + sizeof(PGDIOBJ
) * Size
);
177 handleTable
->wTableSize
= Size
;
178 ExReleaseFastMutexUnsafe (&HandleTableMutex
);
179 KfLowerIrql(PrevIrql
);
185 * Returns the entry into the handle table by index.
187 static PGDIOBJHDR FASTCALL
188 GDIOBJ_iGetObjectForIndex(WORD TableIndex
)
190 if (0 == TableIndex
|| HandleTable
->wTableSize
< TableIndex
)
192 DPRINT1("Invalid TableIndex %u\n", (unsigned) TableIndex
);
196 return HandleTable
->Handles
[TableIndex
];
200 * Finds next free entry in the GDI handle table.
201 * \return index into the table is successful, zero otherwise.
204 GDIOBJ_iGetNextOpenHandleIndex (void)
208 /* prevent APC delivery for the *FastMutexUnsafe calls */
209 const KIRQL PrevIrql
= KfRaiseIrql(APC_LEVEL
);
210 ExAcquireFastMutexUnsafe (&HandleTableMutex
);
211 for (tableIndex
= 1; tableIndex
< HandleTable
->wTableSize
; tableIndex
++)
213 if (NULL
== HandleTable
->Handles
[tableIndex
])
215 HandleTable
->Handles
[tableIndex
] = (PGDIOBJHDR
) -1;
219 ExReleaseFastMutexUnsafe (&HandleTableMutex
);
220 KfLowerIrql(PrevIrql
);
222 return (tableIndex
< HandleTable
->wTableSize
) ? tableIndex
: 0;
226 * Allocate memory for GDI object and return handle to it.
228 * \param Size - size of the GDI object. This shouldn't to include the size of GDIOBJHDR.
229 * The actual amount of allocated memory is sizeof(GDIOBJHDR)+Size
230 * \param ObjectType - type of object \ref GDI object types
231 * \param CleanupProcPtr - Routine to be called on destruction of object
233 * \return Handle of the allocated object.
235 * \note Use GDIOBJ_Lock() to obtain pointer to the new object.
238 GDIOBJ_AllocObj(WORD Size
, DWORD ObjectType
, GDICLEANUPPROC CleanupProc
)
240 PW32PROCESS W32Process
;
241 PGDIOBJHDR newObject
;
244 Index
= GDIOBJ_iGetNextOpenHandleIndex ();
247 DPRINT1("Out of GDI handles\n");
251 DPRINT("GDIOBJ_AllocObj: handle: %d, size: %d, type: 0x%08x\n", Index
, Size
, ObjectType
);
252 newObject
= ExAllocatePool(PagedPool
, Size
+ sizeof (GDIOBJHDR
));
253 if (newObject
== NULL
)
255 DPRINT1("GDIOBJ_AllocObj: failed\n");
258 RtlZeroMemory (newObject
, Size
+ sizeof(GDIOBJHDR
));
260 newObject
->wTableIndex
= Index
;
262 newObject
->dwCount
= 0;
263 newObject
->hProcessId
= PsGetCurrentProcessId ();
264 newObject
->CleanupProc
= CleanupProc
;
265 newObject
->Magic
= GDI_TYPE_TO_MAGIC(ObjectType
);
266 newObject
->lockfile
= NULL
;
267 newObject
->lockline
= 0;
268 HandleTable
->Handles
[Index
] = newObject
;
270 W32Process
= PsGetCurrentProcess()->Win32Process
;
273 W32Process
->GDIObjects
++;
276 return GDI_HANDLE_CREATE(Index
, ObjectType
);
280 * Free memory allocated for the GDI object. For each object type this function calls the
281 * appropriate cleanup routine.
283 * \param hObj - handle of the object to be deleted.
284 * \param ObjectType - one of the \ref GDI object types
285 * or GDI_OBJECT_TYPE_DONTCARE.
286 * \param Flag - if set to GDIOBJFLAG_IGNOREPID then the routine doesn't check if the process that
287 * tries to delete the object is the same one that created it.
289 * \return Returns TRUE if succesful.
291 * \note You should only use GDIOBJFLAG_IGNOREPID if you are cleaning up after the process that terminated.
292 * \note This function deferres object deletion if it is still in use.
295 GDIOBJ_FreeObj(HGDIOBJ hObj
, DWORD ObjectType
, DWORD Flag
)
297 PW32PROCESS W32Process
;
298 PGDIOBJHDR objectHeader
;
302 objectHeader
= GDIOBJ_iGetObjectForIndex(GDI_HANDLE_GET_INDEX(hObj
));
303 DPRINT("GDIOBJ_FreeObj: hObj: 0x%08x, object: %x\n", hObj
, objectHeader
);
305 if (! GDI_VALID_OBJECT(hObj
, objectHeader
, ObjectType
, Flag
)
306 || GDI_GLOBAL_PROCESS
== objectHeader
->hProcessId
)
309 DPRINT1("Can't delete hObj:0x%08x, type:0x%08x, flag:%d\n", hObj
, ObjectType
, Flag
);
313 DPRINT("FreeObj: locks: %x\n", objectHeader
->dwCount
);
314 if (!(Flag
& GDIOBJFLAG_IGNORELOCK
))
316 /* check that the reference count is zero. if not then set flag
317 * and delete object when releaseobj is called */
318 ExAcquireFastMutex(&RefCountHandling
);
319 if ((objectHeader
->dwCount
& ~0x80000000) > 0 )
321 DPRINT("GDIOBJ_FreeObj: delayed object deletion: count %d\n", objectHeader
->dwCount
);
322 objectHeader
->dwCount
|= 0x80000000;
323 ExReleaseFastMutex(&RefCountHandling
);
326 ExReleaseFastMutex(&RefCountHandling
);
329 /* allow object to delete internal data */
330 if (NULL
!= objectHeader
->CleanupProc
)
332 Obj
= (PGDIOBJ
)((PCHAR
)objectHeader
+ sizeof(GDIOBJHDR
));
333 bRet
= (*(objectHeader
->CleanupProc
))(Obj
);
336 ExFreePool(objectHeader
);
337 HandleTable
->Handles
[GDI_HANDLE_GET_INDEX(hObj
)] = NULL
;
339 W32Process
= PsGetCurrentProcess()->Win32Process
;
342 W32Process
->GDIObjects
--;
349 * Lock multiple objects. Use this function when you need to lock multiple objects and some of them may be
350 * duplicates. You should use this function to avoid trying to lock the same object twice!
352 * \param pList pointer to the list that contains handles to the objects. You should set hObj and ObjectType fields.
353 * \param nObj number of objects to lock
354 * \return for each entry in pList this function sets pObj field to point to the object.
356 * \note this function uses an O(n^2) algoritm because we shouldn't need to call it with more than 3 or 4 objects.
359 GDIOBJ_LockMultipleObj(PGDIMULTILOCK pList
, INT nObj
)
363 /* FIXME - check for "invalid" handles */
364 /* go through the list checking for duplicate objects */
365 for (i
= 0; i
< nObj
; i
++)
367 pList
[i
].pObj
= NULL
;
368 for (j
= 0; j
< i
; j
++)
370 if (pList
[i
].hObj
== pList
[j
].hObj
)
372 /* already locked, so just copy the pointer to the object */
373 pList
[i
].pObj
= pList
[j
].pObj
;
378 if (NULL
== pList
[i
].pObj
)
380 /* object hasn't been locked, so lock it. */
381 if (NULL
!= pList
[i
].hObj
)
383 pList
[i
].pObj
= GDIOBJ_LockObj(pList
[i
].hObj
, pList
[i
].ObjectType
);
392 * Unlock multiple objects. Use this function when you need to unlock multiple objects and some of them may be
395 * \param pList pointer to the list that contains handles to the objects. You should set hObj and ObjectType fields.
396 * \param nObj number of objects to lock
398 * \note this function uses O(n^2) algoritm because we shouldn't need to call it with more than 3 or 4 objects.
401 GDIOBJ_UnlockMultipleObj(PGDIMULTILOCK pList
, INT nObj
)
406 /* go through the list checking for duplicate objects */
407 for (i
= 0; i
< nObj
; i
++)
409 if (NULL
!= pList
[i
].pObj
)
411 for (j
= i
+ 1; j
< nObj
; j
++)
413 if ((pList
[i
].pObj
== pList
[j
].pObj
))
415 /* set the pointer to zero for all duplicates */
416 pList
[j
].pObj
= NULL
;
419 GDIOBJ_UnlockObj(pList
[i
].hObj
, pList
[i
].ObjectType
);
420 pList
[i
].pObj
= NULL
;
428 * Marks the object as global. (Creator process ID is set to GDI_GLOBAL_PROCESS). Global objects may be
429 * accessed by any process.
430 * \param ObjectHandle - handle of the object to make global.
432 * \note Only stock objects should be marked global.
435 GDIOBJ_MarkObjectGlobal(HGDIOBJ ObjectHandle
)
438 PW32PROCESS W32Process
;
442 DPRINT("GDIOBJ_MarkObjectGlobal handle 0x%08x\n", ObjectHandle
);
443 ObjHdr
= GDIOBJ_iGetObjectForIndex(GDI_HANDLE_GET_INDEX(ObjectHandle
));
449 Status
= PsLookupProcessByProcessId((PVOID
)ObjHdr
->hProcessId
, &Process
);
450 if(NT_SUCCESS(Status
))
452 W32Process
= Process
->Win32Process
;
455 W32Process
->GDIObjects
--;
459 ObjHdr
->hProcessId
= GDI_GLOBAL_PROCESS
;
463 * Removes the global mark from the object. Global objects may be
464 * accessed by any process.
465 * \param ObjectHandle - handle of the object to make local.
467 * \note Only stock objects should be marked global.
470 GDIOBJ_UnmarkObjectGlobal(HGDIOBJ ObjectHandle
)
472 PW32PROCESS W32Process
;
475 DPRINT("GDIOBJ_MarkObjectGlobal handle 0x%08x\n", ObjectHandle
);
476 ObjHdr
= GDIOBJ_iGetObjectForIndex(GDI_HANDLE_GET_INDEX(ObjectHandle
));
477 if (NULL
== ObjHdr
/*|| GDI_GLOBAL_PROCESS != ObjHdr->hProcessId*/)
482 W32Process
= PsGetCurrentProcess()->Win32Process
;
485 W32Process
->GDIObjects
++;
488 ObjHdr
->hProcessId
= PsGetCurrentProcessId();
492 * Get the type of the object.
493 * \param ObjectHandle - handle of the object.
494 * \return One of the \ref GDI object types
497 GDIOBJ_GetObjectType(HGDIOBJ ObjectHandle
)
501 ObjHdr
= GDIOBJ_iGetObjectForIndex(GDI_HANDLE_GET_INDEX(ObjectHandle
));
503 || ! GDI_VALID_OBJECT(ObjectHandle
, ObjHdr
, GDI_MAGIC_TO_TYPE(ObjHdr
->Magic
), 0))
505 DPRINT1("Invalid ObjectHandle 0x%08x\n", ObjectHandle
);
508 DPRINT("GDIOBJ_GetObjectType for handle 0x%08x returns 0x%08x\n", ObjectHandle
,
509 GDI_MAGIC_TO_TYPE(ObjHdr
->Magic
));
511 return GDI_MAGIC_TO_TYPE(ObjHdr
->Magic
);
515 * Initialization of the GDI object engine.
518 InitGdiObjectHandleTable (VOID
)
520 DPRINT("InitGdiObjectHandleTable\n");
521 ExInitializeFastMutex (&HandleTableMutex
);
522 ExInitializeFastMutex (&RefCountHandling
);
524 HandleTable
= GDIOBJ_iAllocHandleTable (GDI_HANDLE_COUNT
);
525 DPRINT("HandleTable: %x\n", HandleTable
);
527 InitEngHandleTable();
531 * Creates a bunch of stock objects: brushes, pens, fonts.
534 CreateStockObjects(void)
538 DPRINT("Beginning creation of stock objects\n");
540 /* Create GDI Stock Objects from the logical structures we've defined */
542 StockObjects
[WHITE_BRUSH
] = NtGdiCreateBrushIndirect(&WhiteBrush
);
543 StockObjects
[LTGRAY_BRUSH
] = NtGdiCreateBrushIndirect(&LtGrayBrush
);
544 StockObjects
[GRAY_BRUSH
] = NtGdiCreateBrushIndirect(&GrayBrush
);
545 StockObjects
[DKGRAY_BRUSH
] = NtGdiCreateBrushIndirect(&DkGrayBrush
);
546 StockObjects
[BLACK_BRUSH
] = NtGdiCreateBrushIndirect(&BlackBrush
);
547 StockObjects
[NULL_BRUSH
] = NtGdiCreateBrushIndirect(&NullBrush
);
549 StockObjects
[WHITE_PEN
] = NtGdiCreatePenIndirect(&WhitePen
);
550 StockObjects
[BLACK_PEN
] = NtGdiCreatePenIndirect(&BlackPen
);
551 StockObjects
[NULL_PEN
] = NtGdiCreatePenIndirect(&NullPen
);
553 (void) TextIntCreateFontIndirect(&OEMFixedFont
, (HFONT
*)&StockObjects
[OEM_FIXED_FONT
]);
554 (void) TextIntCreateFontIndirect(&AnsiFixedFont
, (HFONT
*)&StockObjects
[ANSI_FIXED_FONT
]);
555 (void) TextIntCreateFontIndirect(&SystemFont
, (HFONT
*)&StockObjects
[SYSTEM_FONT
]);
556 (void) TextIntCreateFontIndirect(&DeviceDefaultFont
, (HFONT
*)&StockObjects
[DEVICE_DEFAULT_FONT
]);
557 (void) TextIntCreateFontIndirect(&SystemFixedFont
, (HFONT
*)&StockObjects
[SYSTEM_FIXED_FONT
]);
558 (void) TextIntCreateFontIndirect(&DefaultGuiFont
, (HFONT
*)&StockObjects
[DEFAULT_GUI_FONT
]);
560 StockObjects
[DEFAULT_PALETTE
] = (HGDIOBJ
*)PALETTE_Init();
562 for (Object
= 0; Object
< NB_STOCK_OBJECTS
; Object
++)
564 if (NULL
!= StockObjects
[Object
])
566 GDIOBJ_MarkObjectGlobal(StockObjects
[Object
]);
567 /* GDI_HANDLE_SET_STOCKOBJ(StockObjects[Object]);*/
571 DPRINT("Completed creation of stock objects\n");
575 * Return stock object.
576 * \param Object - stock object id.
577 * \return Handle to the object.
580 NtGdiGetStockObject(INT Object
)
582 DPRINT("NtGdiGetStockObject index %d\n", Object
);
584 return ((Object
< 0) || (NB_STOCK_OBJECTS
<= Object
)) ? NULL
: StockObjects
[Object
];
589 * \param hObject object handle
590 * \return if the function fails the returned value is FALSE.
593 NtGdiDeleteObject(HGDIOBJ hObject
)
595 DPRINT("NtGdiDeleteObject handle 0x%08x\n", hObject
);
597 return GDIOBJ_FreeObj(hObject
, GDI_OBJECT_TYPE_DONTCARE
, GDIOBJFLAG_DEFAULT
);
601 * Internal function. Called when the process is destroyed to free the remaining GDI handles.
602 * \param Process - PID of the process that will be destroyed.
605 CleanupForProcess (struct _EPROCESS
*Process
, INT Pid
)
608 PGDIOBJHDR objectHeader
;
609 PEPROCESS CurrentProcess
;
611 DPRINT("Starting CleanupForProcess prochandle %x Pid %d\n", Process
, Pid
);
612 CurrentProcess
= PsGetCurrentProcess();
613 if (CurrentProcess
!= Process
)
615 KeAttachProcess(Process
);
618 for(i
= 1; i
< HandleTable
->wTableSize
; i
++)
620 objectHeader
= GDIOBJ_iGetObjectForIndex(i
);
621 if (NULL
!= objectHeader
&&
622 (INT
) objectHeader
->hProcessId
== Pid
)
624 DPRINT("CleanupForProcess: %d, process: %d, locks: %d, magic: 0x%x", i
, objectHeader
->hProcessId
, objectHeader
->dwCount
, objectHeader
->Magic
);
625 GDIOBJ_FreeObj(GDI_HANDLE_CREATE(i
, GDI_MAGIC_TO_TYPE(objectHeader
->Magic
)),
626 GDI_MAGIC_TO_TYPE(objectHeader
->Magic
),
627 GDIOBJFLAG_IGNOREPID
| GDIOBJFLAG_IGNORELOCK
);
631 if (CurrentProcess
!= Process
)
636 DPRINT("Completed cleanup for process %d\n", Pid
);
641 #define GDIOBJ_TRACKLOCKS
643 #ifdef GDIOBJ_LockObj
644 #undef GDIOBJ_LockObj
646 GDIOBJ_LockObjDbg (const char* file
, int line
, HGDIOBJ hObj
, DWORD ObjectType
)
649 PGDIOBJHDR ObjHdr
= GDIOBJ_iGetObjectForIndex(GDI_HANDLE_GET_INDEX(hObj
));
651 if (! GDI_VALID_OBJECT(hObj
, ObjHdr
, ObjectType
, GDIOBJFLAG_DEFAULT
))
658 else if (GDI_MAGIC_TO_TYPE(ObjHdr
->Magic
) != ObjectType
&& ObjectType
!= GDI_OBJECT_TYPE_DONTCARE
)
662 else if (ObjHdr
->hProcessId
!= GDI_GLOBAL_PROCESS
663 && ObjHdr
->hProcessId
!= PsGetCurrentProcessId())
667 else if (GDI_HANDLE_GET_TYPE(hObj
) != ObjectType
&& ObjectType
!= GDI_OBJECT_TYPE_DONTCARE
)
671 DPRINT1("GDIOBJ_LockObj failed for 0x%08x, reqtype 0x%08x reason %d\n",
672 hObj
, ObjectType
, reason
);
673 DPRINT1("\tcalled from: %s:%i\n", file
, line
);
676 if (NULL
!= ObjHdr
->lockfile
)
678 DPRINT1("Caution! GDIOBJ_LockObj trying to lock object (0x%x) second time\n", hObj
);
679 DPRINT1("\tcalled from: %s:%i\n", file
, line
);
680 DPRINT1("\tpreviously locked from: %s:%i\n", ObjHdr
->lockfile
, ObjHdr
->lockline
);
682 DPRINT("(%s:%i) GDIOBJ_LockObj(0x%08x,0x%08x)\n", file
, line
, hObj
, ObjectType
);
683 rc
= GDIOBJ_LockObj(hObj
, ObjectType
);
684 if (rc
&& NULL
== ObjHdr
->lockfile
)
686 ObjHdr
->lockfile
= file
;
687 ObjHdr
->lockline
= line
;
692 #endif//GDIOBJ_LockObj
694 #ifdef GDIOBJ_UnlockObj
695 #undef GDIOBJ_UnlockObj
697 GDIOBJ_UnlockObjDbg (const char* file
, int line
, HGDIOBJ hObj
, DWORD ObjectType
)
699 PGDIOBJHDR ObjHdr
= GDIOBJ_iGetObjectForIndex(GDI_HANDLE_GET_INDEX(hObj
));
701 if (! GDI_VALID_OBJECT(hObj
, ObjHdr
, ObjectType
, GDIOBJFLAG_DEFAULT
))
703 DPRINT1("GDIBOJ_UnlockObj failed for 0x%08x, reqtype 0x%08x\n",
705 DPRINT1("\tcalled from: %s:%i\n", file
, line
);
708 DPRINT("(%s:%i) GDIOBJ_UnlockObj(0x%08x,0x%08x)\n", file
, line
, hObj
, ObjectType
);
709 ObjHdr
->lockfile
= NULL
;
710 ObjHdr
->lockline
= 0;
712 return GDIOBJ_UnlockObj(hObj
, ObjectType
);
714 #endif//GDIOBJ_LockObj
717 * Return pointer to the object by handle.
719 * \param hObj Object handle
720 * \param ObjectType one of the object types defined in \ref GDI object types
721 * \return Pointer to the object.
723 * \note Process can only get pointer to the objects it created or global objects.
725 * \todo Don't allow to lock the objects twice! Synchronization!
728 GDIOBJ_LockObj(HGDIOBJ hObj
, DWORD ObjectType
)
730 PGDIOBJHDR ObjHdr
= GDIOBJ_iGetObjectForIndex(GDI_HANDLE_GET_INDEX(hObj
));
732 DPRINT("GDIOBJ_LockObj: hObj: 0x%08x, type: 0x%08x, objhdr: %x\n", hObj
, ObjectType
, ObjHdr
);
733 if (! GDI_VALID_OBJECT(hObj
, ObjHdr
, ObjectType
, GDIOBJFLAG_DEFAULT
))
735 DPRINT1("GDIBOJ_LockObj failed for 0x%08x, type 0x%08x\n",
740 if(0 < ObjHdr
->dwCount
)
742 DPRINT1("Caution! GDIOBJ_LockObj trying to lock object (0x%x) second time\n", hObj
);
743 DPRINT1("\t called from: %x\n", __builtin_return_address(0));
746 ExAcquireFastMutex(&RefCountHandling
);
748 ExReleaseFastMutex(&RefCountHandling
);
749 return (PGDIOBJ
)((PCHAR
)ObjHdr
+ sizeof(GDIOBJHDR
));
753 * Release GDI object. Every object locked by GDIOBJ_LockObj() must be unlocked. You should unlock the object
754 * as soon as you don't need to have access to it's data.
756 * \param hObj Object handle
757 * \param ObjectType one of the object types defined in \ref GDI object types
759 * \note This function performs delayed cleanup. If the object is locked when GDI_FreeObj() is called
760 * then \em this function frees the object when reference count is zero.
762 * \todo Change synchronization algorithm.
764 #undef GDIOBJ_UnlockObj
766 GDIOBJ_UnlockObj(HGDIOBJ hObj
, DWORD ObjectType
)
768 PGDIOBJHDR ObjHdr
= GDIOBJ_iGetObjectForIndex(GDI_HANDLE_GET_INDEX(hObj
));
770 DPRINT("GDIOBJ_UnlockObj: hObj: 0x%08x, type: 0x%08x, objhdr: %x\n", hObj
, ObjectType
, ObjHdr
);
771 if (! GDI_VALID_OBJECT(hObj
, ObjHdr
, ObjectType
, GDIOBJFLAG_DEFAULT
))
773 DPRINT1( "GDIOBJ_UnLockObj: failed\n");
777 ExAcquireFastMutex(&RefCountHandling
);
778 if (0 == (ObjHdr
->dwCount
& ~0x80000000))
780 ExReleaseFastMutex(&RefCountHandling
);
781 DPRINT1( "GDIOBJ_UnLockObj: unlock object (0x%x) that is not locked\n", hObj
);
787 if (ObjHdr
->dwCount
== 0x80000000)
789 //delayed object release
791 ExReleaseFastMutex(&RefCountHandling
);
792 DPRINT("GDIOBJ_UnlockObj: delayed delete\n");
793 return GDIOBJ_FreeObj(hObj
, ObjectType
, GDIOBJFLAG_DEFAULT
);
795 ExReleaseFastMutex(&RefCountHandling
);
801 GDIOBJ_OwnedByCurrentProcess(HGDIOBJ ObjectHandle
)
803 PGDIOBJHDR ObjHdr
= GDIOBJ_iGetObjectForIndex(GDI_HANDLE_GET_INDEX(ObjectHandle
));
805 DPRINT("GDIOBJ_OwnedByCurrentProcess: ObjectHandle: 0x%08x\n", ObjectHandle
);
806 ASSERT(GDI_VALID_OBJECT(ObjectHandle
, ObjHdr
, GDI_OBJECT_TYPE_DONTCARE
, GDIOBJFLAG_IGNOREPID
));
808 return ObjHdr
->hProcessId
== PsGetCurrentProcessId();
812 GDIOBJ_TakeOwnership(HGDIOBJ ObjectHandle
)
814 PGDIOBJHDR ObjHdr
= GDIOBJ_iGetObjectForIndex(GDI_HANDLE_GET_INDEX(ObjectHandle
));
816 DPRINT("GDIOBJ_OwnedByCurrentProcess: ObjectHandle: 0x%08x\n", ObjectHandle
);
817 ASSERT(GDI_VALID_OBJECT(ObjectHandle
, ObjHdr
, GDI_OBJECT_TYPE_DONTCARE
, GDIOBJFLAG_IGNOREPID
));
819 if (GDI_GLOBAL_PROCESS
!= ObjHdr
->hProcessId
)
821 ObjHdr
->hProcessId
= PsGetCurrentProcessId();