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
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 #define GDI_GLOBAL_PROCESS ((HANDLE) 0xffffffff)
46 #define GDI_HANDLE_INDEX_MASK 0x00000fff
47 #define GDI_HANDLE_TYPE_MASK 0x007f0000
48 #define GDI_HANDLE_STOCK_MASK 0x00800000
50 #define GDI_HANDLE_CREATE(i, t) ((HANDLE)(((i) & GDI_HANDLE_INDEX_MASK) | ((t) & GDI_HANDLE_TYPE_MASK)))
51 #define GDI_HANDLE_GET_INDEX(h) (((DWORD)(h)) & GDI_HANDLE_INDEX_MASK)
52 #define GDI_HANDLE_GET_TYPE(h) (((DWORD)(h)) & GDI_HANDLE_TYPE_MASK)
53 #define GDI_HANDLE_IS_TYPE(h, t) ((t) == (((DWORD)(h)) & GDI_HANDLE_TYPE_MASK))
54 #define GDI_HANDLE_IS_STOCKOBJ(h) (0 != (((DWORD)(h)) & GDI_HANDLE_STOCK_MASK))
55 #define GDI_HANDLE_SET_STOCKOBJ(h) ((h) = (HANDLE)(((DWORD)(h)) | GDI_HANDLE_STOCK_MASK))
57 #define GDI_TYPE_TO_MAGIC(t) ((WORD) ((t) >> 16))
58 #define GDI_MAGIC_TO_TYPE(m) ((DWORD)(m) << 16)
60 #define GDI_VALID_OBJECT(h, obj, t, f) \
62 && (GDI_MAGIC_TO_TYPE((obj)->Magic) == (t) || GDI_OBJECT_TYPE_DONTCARE == (t)) \
63 && (GDI_HANDLE_GET_TYPE((h)) == (t) || GDI_OBJECT_TYPE_DONTCARE == (t)) \
64 && (((obj)->hProcessId == PsGetCurrentProcessId()) \
65 || (GDI_GLOBAL_PROCESS == (obj)->hProcessId) \
66 || ((f) & GDIOBJFLAG_IGNOREPID)))
68 typedef struct _GDI_HANDLE_TABLE
71 PGDIOBJHDR Handles[1];
72 } GDI_HANDLE_TABLE, *PGDI_HANDLE_TABLE;
74 /* GDI stock objects */
76 static LOGBRUSH WhiteBrush =
77 { BS_SOLID, RGB(255,255,255), 0 };
79 static LOGBRUSH LtGrayBrush =
80 /* FIXME : this should perhaps be BS_HATCHED, at least for 1 bitperpixel */
81 { BS_SOLID, RGB(192,192,192), 0 };
83 static LOGBRUSH GrayBrush =
84 /* FIXME : this should perhaps be BS_HATCHED, at least for 1 bitperpixel */
85 { BS_SOLID, RGB(128,128,128), 0 };
87 static LOGBRUSH DkGrayBrush =
88 /* This is BS_HATCHED, for 1 bitperpixel. This makes the spray work in pbrush */
89 /* NB_HATCH_STYLES is an index into HatchBrushes */
90 { BS_HATCHED, RGB(0,0,0), NB_HATCH_STYLES };
92 static LOGBRUSH BlackBrush =
93 { BS_SOLID, RGB(0,0,0), 0 };
95 static LOGBRUSH NullBrush =
98 static LOGPEN WhitePen =
99 { PS_SOLID, { 0, 0 }, RGB(255,255,255) };
101 static LOGPEN BlackPen =
102 { PS_SOLID, { 0, 0 }, RGB(0,0,0) };
104 static LOGPEN NullPen =
105 { PS_NULL, { 0, 0 }, 0 };
107 static LOGFONTW OEMFixedFont =
108 { 14, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, OEM_CHARSET,
109 0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN, L"" };
111 static LOGFONTW AnsiFixedFont =
112 { 14, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
113 0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN, L"" };
115 /*static LOGFONTW AnsiVarFont =
116 *{ 14, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
117 * 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS, L"MS Sans Serif" }; */
119 static LOGFONTW SystemFont =
120 { 14, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
121 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS, L"System" };
123 static LOGFONTW DeviceDefaultFont =
124 { 14, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
125 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS, L"" };
127 static LOGFONTW SystemFixedFont =
128 { 14, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
129 0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN, L"" };
131 /* FIXME: Is this correct? */
132 static LOGFONTW DefaultGuiFont =
133 { 14, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
134 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS, L"MS Sans Serif" };
136 #define NB_STOCK_OBJECTS (DEFAULT_GUI_FONT + 1)
138 static HGDIOBJ *StockObjects[NB_STOCK_OBJECTS];
139 static PGDI_HANDLE_TABLE HandleTable = 0;
140 static FAST_MUTEX HandleTableMutex;
141 static FAST_MUTEX RefCountHandling;
143 /*! Size of the GDI handle table
144 * http://www.windevnet.com/documents/s=7290/wdj9902b/9902b.htm
145 * gdi handle table can hold 0x4000 handles
147 #define GDI_HANDLE_NUMBER 0x4000
150 * Allocate GDI object table.
151 * \param Size - number of entries in the object table.
153 static PGDI_HANDLE_TABLE FASTCALL
154 GDIOBJ_iAllocHandleTable (WORD Size)
156 PGDI_HANDLE_TABLE handleTable;
158 ExAcquireFastMutexUnsafe (&HandleTableMutex);
159 handleTable = ExAllocatePool(PagedPool,
160 sizeof(GDI_HANDLE_TABLE) +
161 sizeof(PGDIOBJ) * Size);
162 ASSERT( handleTable );
165 sizeof(GDI_HANDLE_TABLE) + sizeof(PGDIOBJ) * Size);
166 handleTable->wTableSize = Size;
167 ExReleaseFastMutexUnsafe (&HandleTableMutex);
173 * Returns the entry into the handle table by index.
175 static PGDIOBJHDR FASTCALL
176 GDIOBJ_iGetObjectForIndex(WORD TableIndex)
178 if (0 == TableIndex || HandleTable->wTableSize < TableIndex)
180 DPRINT1("Invalid TableIndex %u\n", (unsigned) TableIndex);
184 return HandleTable->Handles[TableIndex];
188 * Finds next free entry in the GDI handle table.
189 * \return index into the table is successful, zero otherwise.
192 GDIOBJ_iGetNextOpenHandleIndex (void)
196 ExAcquireFastMutexUnsafe (&HandleTableMutex);
197 for (tableIndex = 1; tableIndex < HandleTable->wTableSize; tableIndex++)
199 if (NULL == HandleTable->Handles[tableIndex])
201 HandleTable->Handles[tableIndex] = (PGDIOBJHDR) -1;
205 ExReleaseFastMutexUnsafe (&HandleTableMutex);
207 return (tableIndex < HandleTable->wTableSize) ? tableIndex : 0;
211 * Allocate memory for GDI object and return handle to it.
213 * \param Size - size of the GDI object. This shouldn't to include the size of GDIOBJHDR.
214 * The actual amount of allocated memory is sizeof(GDIOBJHDR)+Size
215 * \param ObjectType - type of object \ref GDI object types
216 * \param CleanupProcPtr - Routine to be called on destruction of object
218 * \return Handle of the allocated object.
220 * \note Use GDIOBJ_Lock() to obtain pointer to the new object.
223 GDIOBJ_AllocObj(WORD Size, DWORD ObjectType, GDICLEANUPPROC CleanupProc)
225 PGDIOBJHDR newObject;
227 DPRINT("GDIOBJ_AllocObj: size: %d, type: 0x%08x\n", Size, ObjectType);
228 newObject = ExAllocatePool(PagedPool, Size + sizeof (GDIOBJHDR));
229 if (newObject == NULL)
231 DPRINT1("GDIOBJ_AllocObj: failed\n");
234 RtlZeroMemory (newObject, Size + sizeof(GDIOBJHDR));
236 newObject->wTableIndex = GDIOBJ_iGetNextOpenHandleIndex ();
237 DPRINT("GDIOBJ_AllocObj: object handle %d\n", newObject->wTableIndex );
238 if (0 == newObject->wTableIndex)
240 DPRINT1("Out of GDI handles\n");
241 ExFreePool(newObject);
245 newObject->dwCount = 0;
246 newObject->hProcessId = PsGetCurrentProcessId ();
247 newObject->CleanupProc = CleanupProc;
248 newObject->Magic = GDI_TYPE_TO_MAGIC(ObjectType);
249 newObject->lockfile = NULL;
250 newObject->lockline = 0;
251 HandleTable->Handles[newObject->wTableIndex] = newObject;
253 return GDI_HANDLE_CREATE(newObject->wTableIndex, ObjectType);
257 * Free memory allocated for the GDI object. For each object type this function calls the
258 * appropriate cleanup routine.
260 * \param hObj - handle of the object to be deleted.
261 * \param ObjectType - one of the \ref GDI object types
262 * or GDI_OBJECT_TYPE_DONTCARE.
263 * \param Flag - if set to GDIOBJFLAG_IGNOREPID then the routine doesn't check if the process that
264 * tries to delete the object is the same one that created it.
266 * \return Returns TRUE if succesful.
268 * \note You should only use GDIOBJFLAG_IGNOREPID if you are cleaning up after the process that terminated.
269 * \note This function deferres object deletion if it is still in use.
272 GDIOBJ_FreeObj(HGDIOBJ hObj, DWORD ObjectType, DWORD Flag)
274 PGDIOBJHDR objectHeader;
278 objectHeader = GDIOBJ_iGetObjectForIndex(GDI_HANDLE_GET_INDEX(hObj));
279 DPRINT("GDIOBJ_FreeObj: hObj: 0x%08x, object: %x\n", hObj, objectHeader);
281 if (! GDI_VALID_OBJECT(hObj, objectHeader, ObjectType, Flag)
282 || GDI_GLOBAL_PROCESS == objectHeader->hProcessId)
285 DPRINT1("Can't delete hObj:0x%08x, type:0x%08x, flag:%d\n", hObj, ObjectType, Flag);
289 DPRINT("FreeObj: locks: %x\n", objectHeader->dwCount );
290 if (!(Flag & GDIOBJFLAG_IGNORELOCK))
292 /* check that the reference count is zero. if not then set flag
293 * and delete object when releaseobj is called */
294 ExAcquireFastMutex(&RefCountHandling);
295 if ((objectHeader->dwCount & ~0x80000000) > 0 )
297 DPRINT("GDIOBJ_FreeObj: delayed object deletion: count %d\n", objectHeader->dwCount);
298 objectHeader->dwCount |= 0x80000000;
299 ExReleaseFastMutex(&RefCountHandling);
302 ExReleaseFastMutex(&RefCountHandling);
305 /* allow object to delete internal data */
306 if (NULL != objectHeader->CleanupProc)
308 Obj = (PGDIOBJ)((PCHAR)objectHeader + sizeof(GDIOBJHDR));
309 bRet = (*(objectHeader->CleanupProc))(Obj);
312 ExFreePool(objectHeader);
313 HandleTable->Handles[GDI_HANDLE_GET_INDEX(hObj)] = NULL;
319 * Lock multiple objects. Use this function when you need to lock multiple objects and some of them may be
320 * duplicates. You should use this function to avoid trying to lock the same object twice!
322 * \param pList pointer to the list that contains handles to the objects. You should set hObj and ObjectType fields.
323 * \param nObj number of objects to lock
324 * \return for each entry in pList this function sets pObj field to point to the object.
326 * \note this function uses an O(n^2) algoritm because we shouldn't need to call it with more than 3 or 4 objects.
329 GDIOBJ_LockMultipleObj(PGDIMULTILOCK pList, INT nObj)
333 /* FIXME - check for "invalid" handles */
334 /* go through the list checking for duplicate objects */
335 for (i = 0; i < nObj; i++)
337 pList[i].pObj = NULL;
338 for (j = 0; j < i; j++)
340 if (pList[i].hObj == pList[j].hObj)
342 /* already locked, so just copy the pointer to the object */
343 pList[i].pObj = pList[j].pObj;
348 if (NULL == pList[i].pObj)
350 /* object hasn't been locked, so lock it. */
351 if (NULL != pList[i].hObj)
353 pList[i].pObj = GDIOBJ_LockObj(pList[i].hObj, pList[i].ObjectType);
362 * Unlock multiple objects. Use this function when you need to unlock multiple objects and some of them may be
365 * \param pList pointer to the list that contains handles to the objects. You should set hObj and ObjectType fields.
366 * \param nObj number of objects to lock
368 * \note this function uses O(n^2) algoritm because we shouldn't need to call it with more than 3 or 4 objects.
371 GDIOBJ_UnlockMultipleObj(PGDIMULTILOCK pList, INT nObj)
376 /* go through the list checking for duplicate objects */
377 for (i = 0; i < nObj; i++)
379 if (NULL != pList[i].pObj)
381 for (j = i + 1; j < nObj; j++)
383 if ((pList[i].pObj == pList[j].pObj))
385 /* set the pointer to zero for all duplicates */
386 pList[j].pObj = NULL;
389 GDIOBJ_UnlockObj(pList[i].hObj, pList[i].ObjectType);
390 pList[i].pObj = NULL;
398 * Marks the object as global. (Creator process ID is set to GDI_GLOBAL_PROCESS). Global objects may be
399 * accessed by any process.
400 * \param ObjectHandle - handle of the object to make global.
402 * \note Only stock objects should be marked global.
405 GDIOBJ_MarkObjectGlobal(HGDIOBJ ObjectHandle)
409 DPRINT("GDIOBJ_MarkObjectGlobal handle 0x%08x\n", ObjectHandle);
410 ObjHdr = GDIOBJ_iGetObjectForIndex(GDI_HANDLE_GET_INDEX(ObjectHandle));
416 ObjHdr->hProcessId = GDI_GLOBAL_PROCESS;
420 * Removes the global mark from the object. Global objects may be
421 * accessed by any process.
422 * \param ObjectHandle - handle of the object to make local.
424 * \note Only stock objects should be marked global.
427 GDIOBJ_UnmarkObjectGlobal(HGDIOBJ ObjectHandle)
431 DPRINT("GDIOBJ_MarkObjectGlobal handle 0x%08x\n", ObjectHandle);
432 ObjHdr = GDIOBJ_iGetObjectForIndex(GDI_HANDLE_GET_INDEX(ObjectHandle));
433 if (NULL == ObjHdr || GDI_GLOBAL_PROCESS != ObjHdr->hProcessId)
438 ObjHdr->hProcessId = PsGetCurrentProcessId();
442 * Get the type of the object.
443 * \param ObjectHandle - handle of the object.
444 * \return One of the \ref GDI object types
447 GDIOBJ_GetObjectType(HGDIOBJ ObjectHandle)
451 ObjHdr = GDIOBJ_iGetObjectForIndex(GDI_HANDLE_GET_INDEX(ObjectHandle));
454 DPRINT1("Invalid ObjectHandle 0x%08x\n", ObjectHandle);
457 DPRINT("GDIOBJ_GetObjectType for handle 0x%08x returns 0x%08x\n", ObjectHandle,
458 GDI_MAGIC_TO_TYPE(ObjHdr->Magic));
460 return GDI_MAGIC_TO_TYPE(ObjHdr->Magic);
464 * Initialization of the GDI object engine.
467 InitGdiObjectHandleTable (VOID)
469 DPRINT("InitGdiObjectHandleTable\n");
470 ExInitializeFastMutex (&HandleTableMutex);
471 ExInitializeFastMutex (&RefCountHandling);
473 HandleTable = GDIOBJ_iAllocHandleTable (GDI_HANDLE_NUMBER);
474 DPRINT("HandleTable: %x\n", HandleTable );
476 InitEngHandleTable();
480 * Creates a bunch of stock objects: brushes, pens, fonts.
483 CreateStockObjects(void)
487 DPRINT("Beginning creation of stock objects\n");
489 /* Create GDI Stock Objects from the logical structures we've defined */
491 StockObjects[WHITE_BRUSH] = NtGdiCreateBrushIndirect(&WhiteBrush);
492 StockObjects[LTGRAY_BRUSH] = NtGdiCreateBrushIndirect(&LtGrayBrush);
493 StockObjects[GRAY_BRUSH] = NtGdiCreateBrushIndirect(&GrayBrush);
494 StockObjects[DKGRAY_BRUSH] = NtGdiCreateBrushIndirect(&DkGrayBrush);
495 StockObjects[BLACK_BRUSH] = NtGdiCreateBrushIndirect(&BlackBrush);
496 StockObjects[NULL_BRUSH] = NtGdiCreateBrushIndirect(&NullBrush);
498 StockObjects[WHITE_PEN] = NtGdiCreatePenIndirect(&WhitePen);
499 StockObjects[BLACK_PEN] = NtGdiCreatePenIndirect(&BlackPen);
500 StockObjects[NULL_PEN] = NtGdiCreatePenIndirect(&NullPen);
502 (void) TextIntCreateFontIndirect(&OEMFixedFont, (HFONT*)&StockObjects[OEM_FIXED_FONT]);
503 (void) TextIntCreateFontIndirect(&AnsiFixedFont, (HFONT*)&StockObjects[ANSI_FIXED_FONT]);
504 (void) TextIntCreateFontIndirect(&SystemFont, (HFONT*)&StockObjects[SYSTEM_FONT]);
505 (void) TextIntCreateFontIndirect(&DeviceDefaultFont, (HFONT*)&StockObjects[DEVICE_DEFAULT_FONT]);
506 (void) TextIntCreateFontIndirect(&SystemFixedFont, (HFONT*)&StockObjects[SYSTEM_FIXED_FONT]);
507 (void) TextIntCreateFontIndirect(&DefaultGuiFont, (HFONT*)&StockObjects[DEFAULT_GUI_FONT]);
509 StockObjects[DEFAULT_PALETTE] = (HGDIOBJ*)PALETTE_Init();
511 for (Object = 0; Object < NB_STOCK_OBJECTS; Object++)
513 if (NULL != StockObjects[Object])
515 GDIOBJ_MarkObjectGlobal(StockObjects[Object]);
516 /* GDI_HANDLE_SET_STOCKOBJ(StockObjects[Object]);*/
520 DPRINT("Completed creation of stock objects\n");
524 * Return stock object.
525 * \param Object - stock object id.
526 * \return Handle to the object.
529 NtGdiGetStockObject(INT Object)
531 DPRINT("NtGdiGetStockObject index %d\n", Object);
533 return ((Object < 0) || (NB_STOCK_OBJECTS <= Object)) ? NULL : StockObjects[Object];
538 * \param hObject object handle
539 * \return if the function fails the returned value is FALSE.
542 NtGdiDeleteObject(HGDIOBJ hObject)
544 DPRINT("NtGdiDeleteObject handle 0x%08x\n", hObject);
546 return GDIOBJ_FreeObj(hObject, GDI_OBJECT_TYPE_DONTCARE, GDIOBJFLAG_DEFAULT);
550 * Internal function. Called when the process is destroyed to free the remaining GDI handles.
551 * \param Process - PID of the process that will be destroyed.
554 CleanupForProcess (struct _EPROCESS *Process, INT Pid)
557 PGDIOBJHDR objectHeader;
558 PEPROCESS CurrentProcess;
560 DPRINT("Starting CleanupForProcess prochandle %x Pid %d\n", Process, Pid);
561 CurrentProcess = PsGetCurrentProcess();
562 if (CurrentProcess != Process)
564 KeAttachProcess(Process);
567 for(i = 1; i < HandleTable->wTableSize; i++)
569 objectHeader = GDIOBJ_iGetObjectForIndex(i);
570 if (NULL != objectHeader &&
571 (INT) objectHeader->hProcessId == Pid)
573 DPRINT("CleanupForProcess: %d, process: %d, locks: %d, magic: 0x%x", i, objectHeader->hProcessId, objectHeader->dwCount, objectHeader->Magic);
574 GDIOBJ_FreeObj(GDI_HANDLE_CREATE(i, GDI_OBJECT_TYPE_DONTCARE),
575 GDI_OBJECT_TYPE_DONTCARE,
576 GDIOBJFLAG_IGNOREPID | GDIOBJFLAG_IGNORELOCK);
580 if (CurrentProcess != Process)
585 DPRINT("Completed cleanup for process %d\n", Pid);
590 #define GDIOBJ_TRACKLOCKS
592 #ifdef GDIOBJ_LockObj
593 #undef GDIOBJ_LockObj
595 GDIOBJ_LockObjDbg (const char* file, int line, HGDIOBJ hObj, DWORD ObjectType)
598 PGDIOBJHDR ObjHdr = GDIOBJ_iGetObjectForIndex(GDI_HANDLE_GET_INDEX(hObj));
600 if (! GDI_VALID_OBJECT(hObj, ObjHdr, ObjectType, GDIOBJFLAG_DEFAULT))
607 else if (GDI_MAGIC_TO_TYPE(ObjHdr->Magic) != ObjectType && ObjectType != GDI_OBJECT_TYPE_DONTCARE)
611 else if (ObjHdr->hProcessId != GDI_GLOBAL_PROCESS
612 && ObjHdr->hProcessId != PsGetCurrentProcessId())
616 else if (GDI_HANDLE_GET_TYPE(hObj) != ObjectType && ObjectType != GDI_OBJECT_TYPE_DONTCARE)
620 DPRINT1("GDIOBJ_LockObj failed for 0x%08x, reqtype 0x%08x reason %d\n",
621 hObj, ObjectType, reason );
622 DPRINT1("\tcalled from: %s:%i\n", file, line );
625 if (NULL != ObjHdr->lockfile)
627 DPRINT1("Caution! GDIOBJ_LockObj trying to lock object (0x%x) second time\n", hObj );
628 DPRINT1("\tcalled from: %s:%i\n", file, line );
629 DPRINT1("\tpreviously locked from: %s:%i\n", ObjHdr->lockfile, ObjHdr->lockline );
631 DPRINT("(%s:%i) GDIOBJ_LockObj(0x%08x,0x%08x)\n", file, line, hObj, ObjectType);
632 rc = GDIOBJ_LockObj(hObj, ObjectType);
633 if (rc && NULL == ObjHdr->lockfile)
635 ObjHdr->lockfile = file;
636 ObjHdr->lockline = line;
641 #endif//GDIOBJ_LockObj
643 #ifdef GDIOBJ_UnlockObj
644 #undef GDIOBJ_UnlockObj
646 GDIOBJ_UnlockObjDbg (const char* file, int line, HGDIOBJ hObj, DWORD ObjectType)
648 PGDIOBJHDR ObjHdr = GDIOBJ_iGetObjectForIndex(GDI_HANDLE_GET_INDEX(hObj));
650 if (! GDI_VALID_OBJECT(hObj, ObjHdr, ObjectType, GDIOBJFLAG_DEFAULT))
652 DPRINT1("GDIBOJ_UnlockObj failed for 0x%08x, reqtype 0x%08x\n",
654 DPRINT1("\tcalled from: %s:%i\n", file, line);
657 DPRINT("(%s:%i) GDIOBJ_UnlockObj(0x%08x,0x%08x)\n", file, line, hObj, ObjectType);
658 ObjHdr->lockfile = NULL;
659 ObjHdr->lockline = 0;
661 return GDIOBJ_UnlockObj(hObj, ObjectType);
663 #endif//GDIOBJ_LockObj
666 * Return pointer to the object by handle.
668 * \param hObj Object handle
669 * \param ObjectType one of the object types defined in \ref GDI object types
670 * \return Pointer to the object.
672 * \note Process can only get pointer to the objects it created or global objects.
674 * \todo Don't allow to lock the objects twice! Synchronization!
677 GDIOBJ_LockObj(HGDIOBJ hObj, DWORD ObjectType)
679 PGDIOBJHDR ObjHdr = GDIOBJ_iGetObjectForIndex(GDI_HANDLE_GET_INDEX(hObj));
681 DPRINT("GDIOBJ_LockObj: hObj: 0x%08x, type: 0x%08x, objhdr: %x\n", hObj, ObjectType, ObjHdr);
682 if (! GDI_VALID_OBJECT(hObj, ObjHdr, ObjectType, GDIOBJFLAG_DEFAULT))
684 DPRINT1("GDIBOJ_LockObj failed for 0x%08x, type 0x%08x\n",
689 if(0 < ObjHdr->dwCount)
691 DPRINT1("Caution! GDIOBJ_LockObj trying to lock object (0x%x) second time\n", hObj);
692 DPRINT1("\t called from: %x\n", __builtin_return_address(0));
695 ExAcquireFastMutex(&RefCountHandling);
697 ExReleaseFastMutex(&RefCountHandling);
698 return (PGDIOBJ)((PCHAR)ObjHdr + sizeof(GDIOBJHDR));
702 * Release GDI object. Every object locked by GDIOBJ_LockObj() must be unlocked. You should unlock the object
703 * as soon as you don't need to have access to it's data.
705 * \param hObj Object handle
706 * \param ObjectType one of the object types defined in \ref GDI object types
708 * \note This function performs delayed cleanup. If the object is locked when GDI_FreeObj() is called
709 * then \em this function frees the object when reference count is zero.
711 * \todo Change synchronization algorithm.
713 #undef GDIOBJ_UnlockObj
715 GDIOBJ_UnlockObj(HGDIOBJ hObj, DWORD ObjectType)
717 PGDIOBJHDR ObjHdr = GDIOBJ_iGetObjectForIndex(GDI_HANDLE_GET_INDEX(hObj));
719 DPRINT("GDIOBJ_UnlockObj: hObj: 0x%08x, type: 0x%08x, objhdr: %x\n", hObj, ObjectType, ObjHdr);
720 if (! GDI_VALID_OBJECT(hObj, ObjHdr, ObjectType, GDIOBJFLAG_DEFAULT))
722 DPRINT1( "GDIOBJ_UnLockObj: failed\n");
726 ExAcquireFastMutex(&RefCountHandling);
727 if (0 == (ObjHdr->dwCount & ~0x80000000))
729 ExReleaseFastMutex(&RefCountHandling);
730 DPRINT1( "GDIOBJ_UnLockObj: unlock object (0x%x) that is not locked\n", hObj );
736 if (ObjHdr->dwCount == 0x80000000)
738 //delayed object release
740 ExReleaseFastMutex(&RefCountHandling);
741 DPRINT("GDIOBJ_UnlockObj: delayed delete\n");
742 return GDIOBJ_FreeObj(hObj, ObjectType, GDIOBJFLAG_DEFAULT);
744 ExReleaseFastMutex(&RefCountHandling);