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.34 2003/08/11 21:10:49 royce 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 #define GDI_HANDLE2INDEX(h) (((WORD)(size_t)(h)) & 0xffff)
45 #define GDI_INDEX2HANDLE(i) ((HANDLE) (((size_t)(i))&0xffff) )
49 static LOGBRUSH WhiteBrush
=
50 { BS_SOLID
, RGB(255,255,255), 0 };
52 static LOGBRUSH LtGrayBrush
=
53 /* FIXME : this should perhaps be BS_HATCHED, at least for 1 bitperpixel */
54 { BS_SOLID
, RGB(192,192,192), 0 };
56 static LOGBRUSH GrayBrush
=
57 /* FIXME : this should perhaps be BS_HATCHED, at least for 1 bitperpixel */
58 { BS_SOLID
, RGB(128,128,128), 0 };
60 static LOGBRUSH DkGrayBrush
=
61 /* This is BS_HATCHED, for 1 bitperpixel. This makes the spray work in pbrush */
62 /* NB_HATCH_STYLES is an index into HatchBrushes */
63 { BS_HATCHED
, RGB(0,0,0), NB_HATCH_STYLES
};
65 static LOGBRUSH BlackBrush
=
66 { BS_SOLID
, RGB(0,0,0), 0 };
68 static LOGBRUSH NullBrush
=
71 static LOGPEN WhitePen
=
72 { PS_SOLID
, { 0, 0 }, RGB(255,255,255) };
74 static LOGPEN BlackPen
=
75 { PS_SOLID
, { 0, 0 }, RGB(0,0,0) };
77 static LOGPEN NullPen
=
78 { PS_NULL
, { 0, 0 }, 0 };
80 static LOGFONTW OEMFixedFont
=
81 { 14, 0, 0, 0, FW_NORMAL
, FALSE
, FALSE
, FALSE
, OEM_CHARSET
,
82 0, 0, DEFAULT_QUALITY
, FIXED_PITCH
| FF_MODERN
, L
"" };
84 /* Filler to make the location counter dword aligned again. This is necessary
85 since (a) LOGFONT is packed, (b) gcc places initialised variables in the code
86 segment, and (c) Solaris assembler is stupid. */
87 //static UINT align_OEMFixedFont = 1;
89 static LOGFONTW AnsiFixedFont
=
90 { 14, 0, 0, 0, FW_NORMAL
, FALSE
, FALSE
, FALSE
, ANSI_CHARSET
,
91 0, 0, DEFAULT_QUALITY
, FIXED_PITCH
| FF_MODERN
, L
"" };
93 //static UINT align_AnsiFixedFont = 1;
95 //static LOGFONTW AnsiVarFont =
96 //{ 14, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
97 // 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS, L"MS Sans Serif" };
99 //static UINT align_AnsiVarFont = 1;
101 static LOGFONTW SystemFont
=
102 { 14, 0, 0, 0, FW_NORMAL
, FALSE
, FALSE
, FALSE
, ANSI_CHARSET
,
103 0, 0, DEFAULT_QUALITY
, VARIABLE_PITCH
| FF_SWISS
, L
"System" };
105 //static UINT align_SystemFont = 1;
107 static LOGFONTW DeviceDefaultFont
=
108 { 14, 0, 0, 0, FW_NORMAL
, FALSE
, FALSE
, FALSE
, ANSI_CHARSET
,
109 0, 0, DEFAULT_QUALITY
, VARIABLE_PITCH
| FF_SWISS
, L
"" };
111 //static UINT align_DeviceDefaultFont = 1;
113 static LOGFONTW SystemFixedFont
=
114 { 14, 0, 0, 0, FW_NORMAL
, FALSE
, FALSE
, FALSE
, ANSI_CHARSET
,
115 0, 0, DEFAULT_QUALITY
, FIXED_PITCH
| FF_MODERN
, L
"" };
117 //static UINT align_SystemFixedFont = 1;
119 /* FIXME: Is this correct? */
120 static LOGFONTW DefaultGuiFont
=
121 { 14, 0, 0, 0, FW_NORMAL
, FALSE
, FALSE
, FALSE
, ANSI_CHARSET
,
122 0, 0, DEFAULT_QUALITY
, VARIABLE_PITCH
| FF_SWISS
, L
"MS Sans Serif" };
124 //static UINT align_DefaultGuiFont = 1;
126 static HGDIOBJ
*StockObjects
[NB_STOCK_OBJECTS
]; // we dont assign these statically as WINE does because we might redesign
127 // the way handles work, so it's more dynamic now
130 HBITMAP hPseudoStockBitmap
; /*! 1x1 bitmap for memory DCs */
132 static PGDI_HANDLE_TABLE HandleTable
= 0;
133 static FAST_MUTEX HandleTableMutex
;
134 static FAST_MUTEX RefCountHandling
;
136 /*! Size of the GDI handle table
137 * per http://www.wd-mag.com/articles/1999/9902/9902b/9902b.htm?topic=articles
138 * gdi handle table can hold 0x4000 handles
140 #define GDI_HANDLE_NUMBER 0x4000
143 * Allocate GDI object table.
144 * \param Size - number of entries in the object table.
146 static PGDI_HANDLE_TABLE FASTCALL
147 GDIOBJ_iAllocHandleTable (WORD Size
)
149 PGDI_HANDLE_TABLE handleTable
;
151 ExAcquireFastMutexUnsafe (&HandleTableMutex
);
152 handleTable
= ExAllocatePool(PagedPool
,
153 sizeof (GDI_HANDLE_TABLE
) +
154 sizeof (GDI_HANDLE_ENTRY
) * Size
);
155 ASSERT( handleTable
);
158 sizeof (GDI_HANDLE_TABLE
) + sizeof (GDI_HANDLE_ENTRY
) * Size
);
159 handleTable
->wTableSize
= Size
;
160 ExReleaseFastMutexUnsafe (&HandleTableMutex
);
166 * Returns the entry into the handle table by index.
168 static PGDI_HANDLE_ENTRY FASTCALL
169 GDIOBJ_iGetHandleEntryForIndex (WORD TableIndex
)
171 //DPRINT("GDIOBJ_iGetHandleEntryForIndex: TableIndex: %d,\n handle: %x, ptr: %x\n", TableIndex, HandleTable->Handles [TableIndex], &(HandleTable->Handles [TableIndex]) );
172 //DPRINT("GIG: HandleTable: %x, Handles: %x, \n TableIndex: %x, pt: %x\n", HandleTable, HandleTable->Handles, TableIndex, ((PGDI_HANDLE_ENTRY)HandleTable->Handles+TableIndex));
173 //DPRINT("GIG: Hndl: %x, mag: %x\n", ((PGDI_HANDLE_ENTRY)HandleTable->Handles+TableIndex), ((PGDI_HANDLE_ENTRY)HandleTable->Handles+TableIndex)->wMagic);
174 return ((PGDI_HANDLE_ENTRY
)HandleTable
->Handles
+TableIndex
);
178 * Finds next free entry in the GDI handle table.
179 * \return index into the table is successful, zero otherwise.
182 GDIOBJ_iGetNextOpenHandleIndex (void)
186 ExAcquireFastMutexUnsafe (&HandleTableMutex
);
187 for (tableIndex
= 1; tableIndex
< HandleTable
->wTableSize
; tableIndex
++)
189 if (HandleTable
->Handles
[tableIndex
].wMagic
== 0)
191 HandleTable
->Handles
[tableIndex
].wMagic
= GO_MAGIC_DONTCARE
;
195 ExReleaseFastMutexUnsafe (&HandleTableMutex
);
197 return (tableIndex
< HandleTable
->wTableSize
) ? tableIndex
: 0;
201 * Allocate memory for GDI object and return handle to it.
203 * \param Size - size of the GDI object. This shouldn't to include the size of GDIOBJHDR.
204 * The actual amount of allocated memory is sizeof(GDIOBJHDR)+Size
205 * \param Magic - object magic (see GDI Magic)
207 * \return Handle of the allocated object.
209 * \note Use GDIOBJ_Lock() to obtain pointer to the new object.
212 GDIOBJ_AllocObj(WORD Size
, WORD Magic
)
214 PGDIOBJHDR newObject
;
215 PGDI_HANDLE_ENTRY handleEntry
;
217 DPRINT("GDIOBJ_AllocObj: size: %d, magic: %x\n", Size
, Magic
);
218 newObject
= ExAllocatePool (PagedPool
, Size
+ sizeof (GDIOBJHDR
));
219 if (newObject
== NULL
)
221 DPRINT("GDIOBJ_AllocObj: failed\n");
224 RtlZeroMemory (newObject
, Size
+ sizeof (GDIOBJHDR
));
226 newObject
->wTableIndex
= GDIOBJ_iGetNextOpenHandleIndex ();
227 newObject
->dwCount
= 0;
228 handleEntry
= GDIOBJ_iGetHandleEntryForIndex (newObject
->wTableIndex
);
229 handleEntry
->wMagic
= Magic
;
230 handleEntry
->hProcessId
= PsGetCurrentProcessId ();
231 handleEntry
->pObject
= newObject
;
232 handleEntry
->lockfile
= NULL
;
233 handleEntry
->lockline
= 0;
234 DPRINT("GDIOBJ_AllocObj: object handle %d\n", newObject
->wTableIndex
);
235 return GDI_INDEX2HANDLE(newObject
->wTableIndex
);
239 * Free memory allocated for the GDI object. For each object type this function calls the
240 * appropriate cleanup routine.
242 * \param hObj - handle of the object to be deleted.
243 * \param Magic - object magic or GO_MAGIC_DONTCARE.
244 * \param Flag - if set to GDIOBJFLAG_IGNOREPID then the routine doesn't check if the process that
245 * tries to delete the object is the same one that created it.
247 * \return Returns TRUE if succesful.
249 * \note You should only use GDIOBJFLAG_IGNOREPID if you are cleaning up after the process that terminated.
250 * \note This function deferres object deletion if it is still in use.
253 GDIOBJ_FreeObj(HGDIOBJ hObj
, WORD Magic
, DWORD Flag
)
255 PGDIOBJHDR objectHeader
;
256 PGDI_HANDLE_ENTRY handleEntry
;
260 handleEntry
= GDIOBJ_iGetHandleEntryForIndex ( GDI_HANDLE2INDEX(hObj
) );
261 DPRINT("GDIOBJ_FreeObj: hObj: %d, magic: %x, handleEntry: %x\n", (WORD
)hObj
& 0xffff, Magic
, handleEntry
);
263 if (handleEntry
== 0 || (handleEntry
->wMagic
!= Magic
&& Magic
!= GO_MAGIC_DONTCARE
)
264 || ((handleEntry
->hProcessId
!= PsGetCurrentProcessId()) && !(Flag
& GDIOBJFLAG_IGNOREPID
))){
266 DPRINT("Can't Delete hObj: %d, magic: %x, pid:%d\n currpid:%d, flag:%d, hmm:%d\n",(WORD
)hObj
& 0xffff, handleEntry
->wMagic
, handleEntry
->hProcessId
, PsGetCurrentProcessId(), (Flag
&GDIOBJFLAG_IGNOREPID
), ((handleEntry
->hProcessId
!= PsGetCurrentProcessId()) && !(Flag
&GDIOBJFLAG_IGNOREPID
)) );
270 objectHeader
= handleEntry
->pObject
;
271 ASSERT(objectHeader
);
272 DPRINT("FreeObj: locks: %x\n", objectHeader
->dwCount
);
273 if( !(Flag
& GDIOBJFLAG_IGNORELOCK
) ){
274 // check that the reference count is zero. if not then set flag
275 // and delete object when releaseobj is called
276 ExAcquireFastMutex(&RefCountHandling
);
277 if( ( objectHeader
->dwCount
& ~0x80000000 ) > 0 ){
278 DPRINT("GDIOBJ_FreeObj: delayed object deletion: count %d\n", objectHeader
->dwCount
);
279 objectHeader
->dwCount
|= 0x80000000;
280 ExReleaseFastMutex(&RefCountHandling
);
283 ExReleaseFastMutex(&RefCountHandling
);
286 //allow object to delete internal data
287 Obj
= (PGDIOBJ
)((PCHAR
)handleEntry
->pObject
+ sizeof(GDIOBJHDR
));
288 switch( handleEntry
->wMagic
){
289 case GO_REGION_MAGIC
:
290 bRet
= RGNDATA_InternalDelete( (PROSRGNDATA
) Obj
);
292 case GO_BITMAP_MAGIC
:
293 bRet
= Bitmap_InternalDelete( (PBITMAPOBJ
) Obj
);
296 bRet
= DC_InternalDeleteDC( (PDC
) Obj
);
299 case GO_PALETTE_MAGIC
:
300 case GO_DISABLED_DC_MAGIC
:
301 case GO_META_DC_MAGIC
:
302 case GO_METAFILE_MAGIC
:
303 case GO_METAFILE_DC_MAGIC
:
304 case GO_ENHMETAFILE_MAGIC
:
305 case GO_ENHMETAFILE_DC_MAGIC
:
311 bRet
= DCE_InternalDelete( (PDCE
) Obj
);
313 case GO_ICONCURSOR_MAGIC
:
314 bRet
= IconCursor_InternalDelete( (PICONCURSOROBJ
) Obj
);
317 ExFreePool (handleEntry
->pObject
);
318 memset ( handleEntry
, 0, sizeof(GDI_HANDLE_ENTRY
) );
324 * Lock multiple objects. Use this function when you need to lock multiple objects and some of them may be
325 * duplicates. You should use this function to avoid trying to lock the same object twice!
327 * \param pList pointer to the list that contains handles to the objects. You should set hObj and Magic fields.
328 * \param nObj number of objects to lock
329 * \return for each entry in pList this function sets pObj field to point to the object.
331 * \note this function uses an O(n^2) algoritm because we shouldn't need to call it with more than 3 or 4 objects.
334 GDIOBJ_LockMultipleObj( PGDIMULTILOCK pList
, INT nObj
)
338 // FIXME - check for "invalid" handles
339 //go through the list checking for duplicate objects
340 for( i
= 0; i
< nObj
; i
++ )
342 (pList
+i
)->pObj
= NULL
;
343 for( j
= 0; j
< i
; j
++ )
345 if( ((pList
+i
)->hObj
== (pList
+j
)->hObj
)
346 && ((pList
+i
)->Magic
== (pList
+j
)->Magic
)
349 //already locked, so just copy the pointer to the object
350 (pList
+i
)->pObj
= (pList
+j
)->pObj
;
354 if( (pList
+i
)->pObj
== NULL
)
356 //object hasn't been locked, so lock it.
357 if ( (pList
+i
)->hObj
)
358 (pList
+i
)->pObj
= GDIOBJ_LockObj( (pList
+i
)->hObj
, (pList
+i
)->Magic
);
365 * Unlock multiple objects. Use this function when you need to unlock multiple objects and some of them may be
368 * \param pList pointer to the list that contains handles to the objects. You should set hObj and Magic fields.
369 * \param nObj number of objects to lock
371 * \note this function uses O(n^2) algoritm because we shouldn't need to call it with more than 3 or 4 objects.
374 GDIOBJ_UnlockMultipleObj( PGDIMULTILOCK pList
, INT nObj
)
378 //go through the list checking for duplicate objects
379 for( i
= 0; i
< nObj
; i
++ )
381 if( (pList
+i
)->pObj
!= NULL
)
383 for( j
= i
+1; j
< nObj
; j
++ )
385 if( ((pList
+i
)->pObj
== (pList
+j
)->pObj
) )
387 //set the pointer to zero for all duplicates
388 (pList
+j
)->pObj
= NULL
;
391 GDIOBJ_UnlockObj( (pList
+i
)->hObj
, (pList
+i
)->Magic
);
392 (pList
+i
)->pObj
= NULL
;
399 * Marks the object as global. (Creator process ID is set to 0xFFFFFFFF). Global objects may be
400 * accessed by any process.
401 * \param ObjectHandle - handle of the object to make global.
403 * \note Only stock objects should be marked global.
406 GDIOBJ_MarkObjectGlobal(HGDIOBJ ObjectHandle
)
408 PGDI_HANDLE_ENTRY handleEntry
;
410 if (ObjectHandle
== NULL
)
413 handleEntry
= GDIOBJ_iGetHandleEntryForIndex ( GDI_HANDLE2INDEX(ObjectHandle
) );
414 if (handleEntry
== 0)
417 handleEntry
->hProcessId
= (HANDLE
)0xFFFFFFFF;
421 * Get the type (magic value) of the object.
422 * \param ObjectHandle - handle of the object.
423 * \return GDI Magic value.
426 GDIOBJ_GetHandleMagic (HGDIOBJ ObjectHandle
)
428 PGDI_HANDLE_ENTRY handleEntry
;
430 if (ObjectHandle
== NULL
)
433 handleEntry
= GDIOBJ_iGetHandleEntryForIndex ( GDI_HANDLE2INDEX(ObjectHandle
) );
434 if (handleEntry
== 0 ||
435 (handleEntry
->hProcessId
!= (HANDLE
)0xFFFFFFFF &&
436 handleEntry
->hProcessId
!= PsGetCurrentProcessId ()))
439 return handleEntry
->wMagic
;
443 * Initialization of the GDI object engine.
446 InitGdiObjectHandleTable (VOID
)
448 DPRINT ("InitGdiObjectHandleTable\n");
449 ExInitializeFastMutex (&HandleTableMutex
);
450 ExInitializeFastMutex (&RefCountHandling
);
452 HandleTable
= GDIOBJ_iAllocHandleTable (GDI_HANDLE_NUMBER
);
453 DPRINT("HandleTable: %x\n", HandleTable
);
455 InitEngHandleTable();
459 * Creates a bunch of stock objects: brushes, pens, fonts.
462 CreateStockObjects(void)
464 // Create GDI Stock Objects from the logical structures we've defined
466 StockObjects
[WHITE_BRUSH
] = W32kCreateBrushIndirect(&WhiteBrush
);
467 GDIOBJ_MarkObjectGlobal(StockObjects
[WHITE_BRUSH
]);
468 StockObjects
[LTGRAY_BRUSH
] = W32kCreateBrushIndirect(&LtGrayBrush
);
469 GDIOBJ_MarkObjectGlobal(StockObjects
[LTGRAY_BRUSH
]);
470 StockObjects
[GRAY_BRUSH
] = W32kCreateBrushIndirect(&GrayBrush
);
471 GDIOBJ_MarkObjectGlobal(StockObjects
[GRAY_BRUSH
]);
472 StockObjects
[DKGRAY_BRUSH
] = W32kCreateBrushIndirect(&DkGrayBrush
);
473 GDIOBJ_MarkObjectGlobal(StockObjects
[DKGRAY_BRUSH
]);
474 StockObjects
[BLACK_BRUSH
] = W32kCreateBrushIndirect(&BlackBrush
);
475 GDIOBJ_MarkObjectGlobal(StockObjects
[BLACK_BRUSH
]);
476 StockObjects
[NULL_BRUSH
] = W32kCreateBrushIndirect(&NullBrush
);
477 GDIOBJ_MarkObjectGlobal(StockObjects
[NULL_BRUSH
]);
479 StockObjects
[WHITE_PEN
] = W32kCreatePenIndirect(&WhitePen
);
480 GDIOBJ_MarkObjectGlobal(StockObjects
[WHITE_PEN
]);
481 StockObjects
[BLACK_PEN
] = W32kCreatePenIndirect(&BlackPen
);
482 GDIOBJ_MarkObjectGlobal(StockObjects
[BLACK_PEN
]);
483 StockObjects
[NULL_PEN
] = W32kCreatePenIndirect(&NullPen
);
484 GDIOBJ_MarkObjectGlobal(StockObjects
[NULL_PEN
]);
486 (void) TextIntCreateFontIndirect(&OEMFixedFont
, (HFONT
*)&StockObjects
[OEM_FIXED_FONT
]);
487 GDIOBJ_MarkObjectGlobal(StockObjects
[OEM_FIXED_FONT
]);
488 (void) TextIntCreateFontIndirect(&AnsiFixedFont
, (HFONT
*)&StockObjects
[ANSI_FIXED_FONT
]);
489 GDIOBJ_MarkObjectGlobal(StockObjects
[ANSI_FIXED_FONT
]);
490 (void) TextIntCreateFontIndirect(&SystemFont
, (HFONT
*)&StockObjects
[SYSTEM_FONT
]);
491 GDIOBJ_MarkObjectGlobal(StockObjects
[SYSTEM_FONT
]);
492 (void) TextIntCreateFontIndirect(&DeviceDefaultFont
, (HFONT
*)&StockObjects
[DEVICE_DEFAULT_FONT
]);
493 GDIOBJ_MarkObjectGlobal(StockObjects
[DEVICE_DEFAULT_FONT
]);
494 (void) TextIntCreateFontIndirect(&SystemFixedFont
, (HFONT
*)&StockObjects
[SYSTEM_FIXED_FONT
]);
495 GDIOBJ_MarkObjectGlobal(StockObjects
[SYSTEM_FIXED_FONT
]);
496 (void) TextIntCreateFontIndirect(&DefaultGuiFont
, (HFONT
*)&StockObjects
[DEFAULT_GUI_FONT
]);
497 GDIOBJ_MarkObjectGlobal(StockObjects
[DEFAULT_GUI_FONT
]);
499 StockObjects
[DEFAULT_PALETTE
] = (HGDIOBJ
*)PALETTE_Init();
503 * Return stock object.
504 * \param Object - stock object id.
505 * \return Handle to the object.
508 W32kGetStockObject(INT Object
)
510 // check when adding new objects
511 if( (Object
< 0) || (Object
>= NB_STOCK_OBJECTS
) )
513 return StockObjects
[Object
];
518 * \param hObject object handle
519 * \return if the function fails the returned value is NULL.
522 W32kDeleteObject(HGDIOBJ hObject
)
524 return GDIOBJ_FreeObj( hObject
, GO_MAGIC_DONTCARE
, GDIOBJFLAG_DEFAULT
);
528 * Internal function. Called when the process is destroyed to free the remaining GDI handles.
529 * \param Process - PID of the process that will be destroyed.
532 CleanupForProcess (struct _EPROCESS
*Process
, INT Pid
)
535 PGDI_HANDLE_ENTRY handleEntry
;
536 PGDIOBJHDR objectHeader
;
539 KeAttachProcess(Process
);
541 for(i
= 1; i
< GDI_HANDLE_NUMBER
; i
++)
543 handleEntry
= GDIOBJ_iGetHandleEntryForIndex((WORD
) i
& 0xffff);
544 if (NULL
!= handleEntry
&& 0 != handleEntry
->wMagic
&&
545 (INT
)handleEntry
->hProcessId
== Pid
)
547 objectHeader
= (PGDIOBJHDR
) handleEntry
->pObject
;
548 DPRINT("\nW32kCleanup: %d, magic: %x \n process: %d, locks: %d", i
, handleEntry
->wMagic
, handleEntry
->hProcessId
, objectHeader
->dwCount
);
549 GDIOBJ_FreeObj( GDI_INDEX2HANDLE(i
), GO_MAGIC_DONTCARE
, GDIOBJFLAG_IGNOREPID
|GDIOBJFLAG_IGNORELOCK
);
559 * Internal function. Dumps all the objects for the given process.
560 * \param If process == 0 dump all the objects.
564 W32kDumpGdiObjects( INT Process
)
567 PGDI_HANDLE_ENTRY handleEntry
;
568 PGDIOBJHDR objectHeader
;
570 for( i
=1; i
< GDI_HANDLE_NUMBER
; i
++ ){
571 handleEntry
= GDIOBJ_iGetHandleEntryForIndex ((WORD
) i
& 0xffff);
572 if( handleEntry
&& handleEntry
->wMagic
!= 0 ){
573 objectHeader
= (PGDIOBJHDR
) handleEntry
->pObject
;
574 DPRINT("\nHandle: %d, magic: %x \n process: %d, locks: %d", i
, handleEntry
->wMagic
, handleEntry
->hProcessId
, objectHeader
->dwCount
);
580 #define GDIOBJ_TRACKLOCKS
582 #ifdef GDIOBJ_LockObj
583 #undef GDIOBJ_LockObj
585 GDIOBJ_LockObjDbg ( const char* file
, int line
, HGDIOBJ hObj
, WORD Magic
)
588 PGDI_HANDLE_ENTRY handleEntry
589 = GDIOBJ_iGetHandleEntryForIndex ( GDI_HANDLE2INDEX(hObj
) );
590 if ( handleEntry
== 0
591 || (handleEntry
->wMagic
!= Magic
&& Magic
!= GO_MAGIC_DONTCARE
)
592 || (handleEntry
->hProcessId
!= (HANDLE
)0xFFFFFFFF
593 && handleEntry
->hProcessId
!= PsGetCurrentProcessId ()
597 DPRINT1("GDIBOJ_LockObj failed for %d, magic: %d, reqMagic\n",
598 (WORD
)((size_t)hObj
&0xffff), handleEntry
->wMagic
, Magic
);
599 DPRINT1("\tcalled from: %s:%i\n", file
, line
);
602 if ( handleEntry
->lockfile
)
604 DPRINT1("Caution! GDIOBJ_LockObj trying to lock object (0x%x) second time\n", hObj
);
605 DPRINT1("\tcalled from: %s:%i\n", file
, line
);
606 DPRINT1("\tpreviously locked from: %s:%i\n", handleEntry
->lockfile
, handleEntry
->lockline
);
608 //DbgPrint("(%s:%i) GDIOBJ_LockObj(0x%x,0x%x)\n", file, line, hObj, Magic );
609 rc
= GDIOBJ_LockObj(hObj
,Magic
);
610 if ( rc
&& !handleEntry
->lockfile
)
612 handleEntry
->lockfile
= file
;
613 handleEntry
->lockline
= line
;
617 #endif//GDIOBJ_LockObj
619 #ifdef GDIOBJ_UnlockObj
620 #undef GDIOBJ_UnlockObj
622 GDIOBJ_UnlockObjDbg ( const char* file
, int line
, HGDIOBJ hObj
, WORD Magic
)
624 PGDI_HANDLE_ENTRY handleEntry
625 = GDIOBJ_iGetHandleEntryForIndex ( GDI_HANDLE2INDEX(hObj
) );
626 if ( handleEntry
== 0
627 || (handleEntry
->wMagic
!= Magic
&& Magic
!= GO_MAGIC_DONTCARE
)
628 || (handleEntry
->hProcessId
!= (HANDLE
)0xFFFFFFFF
629 && handleEntry
->hProcessId
!= PsGetCurrentProcessId ()
633 DPRINT1("GDIBOJ_UnlockObj failed for %d, magic: %d, reqMagic\n",
634 (WORD
)((size_t)hObj
& 0xffff), handleEntry
->wMagic
, Magic
);
635 DPRINT1("\tcalled from: %s:%i\n", file
, line
);
638 //DbgPrint("(%s:%i) GDIOBJ_UnlockObj(0x%x,0x%x)\n", file, line, hObj, Magic );
639 handleEntry
->lockfile
= NULL
;
640 handleEntry
->lockline
= 0;
641 return GDIOBJ_UnlockObj(hObj
,Magic
);
643 #endif//GDIOBJ_LockObj
646 * Return pointer to the object by handle.
648 * \param hObj Object handle
649 * \param Magic one of the magic numbers defined in \ref GDI Magic
650 * \return Pointer to the object.
652 * \note Process can only get pointer to the objects it created or global objects.
654 * \todo Don't allow to lock the objects twice! Synchronization!
657 GDIOBJ_LockObj( HGDIOBJ hObj
, WORD Magic
)
659 PGDI_HANDLE_ENTRY handleEntry
660 = GDIOBJ_iGetHandleEntryForIndex ( GDI_HANDLE2INDEX(hObj
) );
661 PGDIOBJHDR objectHeader
;
663 DPRINT("GDIOBJ_LockObj: hObj: %d, magic: %x, \n handleEntry: %x, mag %x\n", hObj
, Magic
, handleEntry
, handleEntry
->wMagic
);
664 if ( handleEntry
== 0
665 || (handleEntry
->wMagic
!= Magic
&& Magic
!= GO_MAGIC_DONTCARE
)
666 || (handleEntry
->hProcessId
!= (HANDLE
)0xFFFFFFFF
667 && handleEntry
->hProcessId
!= PsGetCurrentProcessId ()
671 DPRINT1("GDIBOJ_LockObj failed for %d, magic: %d, reqMagic\n",
672 (WORD
)((size_t)hObj
& 0xffff), handleEntry
->wMagic
, Magic
);
676 objectHeader
= (PGDIOBJHDR
) handleEntry
->pObject
;
677 ASSERT(objectHeader
);
678 if( objectHeader
->dwCount
> 0 )
680 DbgPrint("Caution! GDIOBJ_LockObj trying to lock object (0x%x) second time\n", hObj
);
681 DbgPrint("\t called from: %x\n", __builtin_return_address(0));
684 ExAcquireFastMutex(&RefCountHandling
);
685 objectHeader
->dwCount
++;
686 ExReleaseFastMutex(&RefCountHandling
);
687 return (PGDIOBJ
)((PCHAR
)objectHeader
+ sizeof(GDIOBJHDR
));
691 * Release GDI object. Every object locked by GDIOBJ_LockObj() must be unlocked. You should unlock the object
692 * as soon as you don't need to have access to it's data.
694 * \param hObj Object handle
695 * \param Magic one of the magic numbers defined in \ref GDI Magic
697 * \note This function performs delayed cleanup. If the object is locked when GDI_FreeObj() is called
698 * then \em this function frees the object when reference count is zero.
700 * \todo Change synchronization algorithm.
702 #undef GDIOBJ_UnlockObj
704 GDIOBJ_UnlockObj( HGDIOBJ hObj
, WORD Magic
)
706 PGDI_HANDLE_ENTRY handleEntry
707 = GDIOBJ_iGetHandleEntryForIndex ( GDI_HANDLE2INDEX(hObj
) );
708 PGDIOBJHDR objectHeader
;
710 DPRINT("GDIOBJ_UnlockObj: hObj: %d, magic: %x, \n handleEntry: %x\n", hObj
, Magic
, handleEntry
);
711 if ( handleEntry
== 0
712 || (handleEntry
->wMagic
!= Magic
&& Magic
!= GO_MAGIC_DONTCARE
)
713 || (handleEntry
->hProcessId
!= (HANDLE
)0xFFFFFFFF
714 && handleEntry
->hProcessId
!= PsGetCurrentProcessId ()
718 DPRINT1( "GDIOBJ_UnLockObj: failed\n");
722 objectHeader
= (PGDIOBJHDR
) handleEntry
->pObject
;
723 ASSERT(objectHeader
);
725 ExAcquireFastMutex(&RefCountHandling
);
726 if( ( objectHeader
->dwCount
& ~0x80000000 ) == 0 )
728 ExReleaseFastMutex(&RefCountHandling
);
729 DPRINT( "GDIOBJ_UnLockObj: unlock object (0x%x) that is not locked\n", hObj
);
733 objectHeader
= (PGDIOBJHDR
) handleEntry
->pObject
;
734 ASSERT(objectHeader
);
735 objectHeader
->dwCount
--;
737 if( objectHeader
->dwCount
== 0x80000000 )
739 //delayed object release
740 objectHeader
->dwCount
= 0;
741 ExReleaseFastMutex(&RefCountHandling
);
742 DPRINT("GDIOBJ_UnlockObj: delayed delete\n");
743 return GDIOBJ_FreeObj( hObj
, Magic
, GDIOBJFLAG_DEFAULT
);
745 ExReleaseFastMutex(&RefCountHandling
);