2 * GDIOBJ.C - GDI object manipulation routines
8 #undef WIN32_LEAN_AND_MEAN
10 #include <ddk/ntddk.h>
11 #include <include/dce.h>
12 #include <win32k/gdiobj.h>
13 #include <win32k/brush.h>
14 #include <win32k/pen.h>
15 #include <win32k/text.h>
16 #include <win32k/dc.h>
17 #include <win32k/bitmaps.h>
18 #include <win32k/region.h>
20 #include <win32k/debug1.h>
24 static LOGBRUSH WhiteBrush =
25 { BS_SOLID, RGB(255,255,255), 0 };
27 static LOGBRUSH LtGrayBrush =
28 /* FIXME : this should perhaps be BS_HATCHED, at least for 1 bitperpixel */
29 { BS_SOLID, RGB(192,192,192), 0 };
31 static LOGBRUSH GrayBrush =
32 /* FIXME : this should perhaps be BS_HATCHED, at least for 1 bitperpixel */
33 { BS_SOLID, RGB(128,128,128), 0 };
35 static LOGBRUSH DkGrayBrush =
36 /* This is BS_HATCHED, for 1 bitperpixel. This makes the spray work in pbrush */
37 /* NB_HATCH_STYLES is an index into HatchBrushes */
38 { BS_HATCHED, RGB(0,0,0), NB_HATCH_STYLES };
40 static LOGBRUSH BlackBrush =
41 { BS_SOLID, RGB(0,0,0), 0 };
43 static LOGBRUSH NullBrush =
46 static LOGPEN WhitePen =
47 { PS_SOLID, { 0, 0 }, RGB(255,255,255) };
49 static LOGPEN BlackPen =
50 { PS_SOLID, { 0, 0 }, RGB(0,0,0) };
52 static LOGPEN NullPen =
53 { PS_NULL, { 0, 0 }, 0 };
55 static LOGFONTW OEMFixedFont =
56 { 0, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, OEM_CHARSET,
57 0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN, L"" };
59 /* Filler to make the location counter dword aligned again. This is necessary
60 since (a) LOGFONT is packed, (b) gcc places initialised variables in the code
61 segment, and (c) Solaris assembler is stupid. */
62 static UINT align_OEMFixedFont = 1;
64 static LOGFONTW AnsiFixedFont =
65 { 0, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
66 0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN, L"" };
68 static UINT align_AnsiFixedFont = 1;
70 static LOGFONTW AnsiVarFont =
71 { 0, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
72 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS, L"MS Sans Serif" };
74 static UINT align_AnsiVarFont = 1;
76 static LOGFONTW SystemFont =
77 { 0, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
78 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS, L"System" };
80 static UINT align_SystemFont = 1;
82 static LOGFONTW DeviceDefaultFont =
83 { 0, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
84 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS, L"" };
86 static UINT align_DeviceDefaultFont = 1;
88 static LOGFONTW SystemFixedFont =
89 { 0, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
90 0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN, L"" };
92 static UINT align_SystemFixedFont = 1;
94 /* FIXME: Is this correct? */
95 static LOGFONTW DefaultGuiFont =
96 { 0, 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_DefaultGuiFont = 1;
101 static HGDIOBJ *StockObjects[NB_STOCK_OBJECTS]; // we dont assign these statically as WINE does because we might redesign
102 // the way handles work, so it's more dynamic now
105 HBITMAP hPseudoStockBitmap; /*! 1x1 bitmap for memory DCs */
107 static PGDI_HANDLE_TABLE HandleTable = 0;
108 static FAST_MUTEX HandleTableMutex;
109 static FAST_MUTEX RefCountHandling;
111 /*! Size of the GDI handle table
112 * per http://www.wd-mag.com/articles/1999/9902/9902b/9902b.htm?topic=articles
113 * gdi handle table can hold 0x4000 handles
115 #define GDI_HANDLE_NUMBER 0x4000
118 * Allocate GDI object table.
119 * \param Size - number of entries in the object table.
121 static PGDI_HANDLE_TABLE
122 GDIOBJ_iAllocHandleTable (WORD Size)
124 PGDI_HANDLE_TABLE handleTable;
126 ExAcquireFastMutexUnsafe (&HandleTableMutex);
127 handleTable = ExAllocatePool(PagedPool,
128 sizeof (GDI_HANDLE_TABLE) +
129 sizeof (GDI_HANDLE_ENTRY) * Size);
130 ASSERT( handleTable );
133 sizeof (GDI_HANDLE_TABLE) + sizeof (GDI_HANDLE_ENTRY) * Size);
134 handleTable->wTableSize = Size;
135 ExReleaseFastMutexUnsafe (&HandleTableMutex);
141 * Returns the entry into the handle table by index.
143 static PGDI_HANDLE_ENTRY
144 GDIOBJ_iGetHandleEntryForIndex (WORD TableIndex)
146 //DPRINT("GDIOBJ_iGetHandleEntryForIndex: TableIndex: %d,\n handle: %x, ptr: %x\n", TableIndex, HandleTable->Handles [TableIndex], &(HandleTable->Handles [TableIndex]) );
147 //DPRINT("GIG: HandleTable: %x, Handles: %x, \n TableIndex: %x, pt: %x\n", HandleTable, HandleTable->Handles, TableIndex, ((PGDI_HANDLE_ENTRY)HandleTable->Handles+TableIndex));
148 //DPRINT("GIG: Hndl: %x, mag: %x\n", ((PGDI_HANDLE_ENTRY)HandleTable->Handles+TableIndex), ((PGDI_HANDLE_ENTRY)HandleTable->Handles+TableIndex)->wMagic);
149 return ((PGDI_HANDLE_ENTRY)HandleTable->Handles+TableIndex);
153 * Finds next free entry in the GDI handle table.
154 * \return index into the table is successful, zero otherwise.
157 GDIOBJ_iGetNextOpenHandleIndex (void)
161 ExAcquireFastMutexUnsafe (&HandleTableMutex);
162 for (tableIndex = 1; tableIndex < HandleTable->wTableSize; tableIndex++)
164 if (HandleTable->Handles [tableIndex].wMagic == 0)
166 HandleTable->Handles [tableIndex].wMagic = GO_MAGIC_DONTCARE;
170 ExReleaseFastMutexUnsafe (&HandleTableMutex);
172 return (tableIndex < HandleTable->wTableSize) ? tableIndex : 0;
176 * Allocate memory for GDI object and return handle to it.
178 * \param Size - size of the GDI object. This shouldn't to include the size of GDIOBJHDR.
179 * The actual amount of allocated memory is sizeof(GDIOBJHDR)+Size
180 * \param Magic - object magic (see GDI Magic)
182 * \return Handle of the allocated object.
184 * \note Use GDIOBJ_Lock() to obtain pointer to the new object.
186 HGDIOBJ GDIOBJ_AllocObj(WORD Size, WORD Magic)
188 PGDIOBJHDR newObject;
189 PGDI_HANDLE_ENTRY handleEntry;
191 DPRINT("GDIOBJ_AllocObj: size: %d, magic: %x\n", Size, Magic);
192 newObject = ExAllocatePool (PagedPool, Size + sizeof (GDIOBJHDR));
193 if (newObject == NULL)
195 DPRINT("GDIOBJ_AllocObj: failed\n");
198 RtlZeroMemory (newObject, Size + sizeof (GDIOBJHDR));
200 newObject->wTableIndex = GDIOBJ_iGetNextOpenHandleIndex ();
201 newObject->dwCount = 0;
202 handleEntry = GDIOBJ_iGetHandleEntryForIndex (newObject->wTableIndex);
203 handleEntry->wMagic = Magic;
204 handleEntry->hProcessId = PsGetCurrentProcessId ();
205 handleEntry->pObject = newObject;
206 DPRINT("GDIOBJ_AllocObj: object handle %d\n", newObject->wTableIndex );
207 return (HGDIOBJ) newObject->wTableIndex;
211 * Free memory allocated for the GDI object. For each object type this function calls the
212 * appropriate cleanup routine.
214 * \param hObj - handle of the object to be deleted.
215 * \param Magic - object magic or GO_MAGIC_DONTCARE.
216 * \param Flag - if set to GDIOBJFLAG_IGNOREPID then the routine doesn't check if the process that
217 * tries to delete the object is the same one that created it.
219 * \return Returns TRUE if succesful.
221 * \note You should only use GDIOBJFLAG_IGNOREPID if you are cleaning up after the process that terminated.
222 * \note This function deferres object deletion if it is still in use.
224 BOOL GDIOBJ_FreeObj(HGDIOBJ hObj, WORD Magic, DWORD Flag)
226 PGDIOBJHDR objectHeader;
227 PGDI_HANDLE_ENTRY handleEntry;
231 handleEntry = GDIOBJ_iGetHandleEntryForIndex ((WORD)hObj & 0xffff);
232 DPRINT("GDIOBJ_FreeObj: hObj: %d, magic: %x, handleEntry: %x\n", (WORD)hObj & 0xffff, Magic, handleEntry );
234 if (handleEntry == 0 || (handleEntry->wMagic != Magic && Magic != GO_MAGIC_DONTCARE )
235 || ((handleEntry->hProcessId != PsGetCurrentProcessId()) && !(Flag & GDIOBJFLAG_IGNOREPID))){
237 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)) );
241 objectHeader = (PGDIOBJHDR) handleEntry->pObject;
242 ASSERT(objectHeader);
243 DPRINT("FreeObj: locks: %x\n", objectHeader->dwCount );
244 if( !(Flag & GDIOBJFLAG_IGNORELOCK) ){
245 // check that the reference count is zero. if not then set flag
246 // and delete object when releaseobj is called
247 ExAcquireFastMutex(&RefCountHandling);
248 if( ( objectHeader->dwCount & ~0x80000000 ) > 0 ){
249 DPRINT("GDIOBJ_FreeObj: delayed object deletion: count %d\n", objectHeader->dwCount);
250 objectHeader->dwCount |= 0x80000000;
251 ExReleaseFastMutex(&RefCountHandling);
254 ExReleaseFastMutex(&RefCountHandling);
257 //allow object to delete internal data
258 Obj = (PGDIOBJ)((PCHAR)handleEntry->pObject + sizeof(GDIOBJHDR));
259 switch( handleEntry->wMagic ){
260 case GO_REGION_MAGIC:
261 bRet = RGNDATA_InternalDelete( (PROSRGNDATA) Obj );
263 case GO_BITMAP_MAGIC:
264 bRet = Bitmap_InternalDelete( (PBITMAPOBJ) Obj );
267 bRet = DC_InternalDeleteDC( (PDC) Obj );
270 case GO_PALETTE_MAGIC:
271 case GO_DISABLED_DC_MAGIC:
272 case GO_META_DC_MAGIC:
273 case GO_METAFILE_MAGIC:
274 case GO_METAFILE_DC_MAGIC:
275 case GO_ENHMETAFILE_MAGIC:
276 case GO_ENHMETAFILE_DC_MAGIC:
282 bRet = DCE_InternalDelete( (PDCE) Obj );
285 handleEntry->hProcessId = 0;
286 ExFreePool (handleEntry->pObject);
287 handleEntry->pObject = 0;
288 handleEntry->wMagic = 0;
294 * Return pointer to the object by handle.
296 * \param hObj Object handle
297 * \param Magic one of the magic numbers defined in \ref GDI Magic
298 * \return Pointer to the object.
300 * \note Process can only get pointer to the objects it created or global objects.
302 * \todo Don't allow to lock the objects twice! Synchronization!
304 PGDIOBJ GDIOBJ_LockObj( HGDIOBJ hObj, WORD Magic )
306 PGDI_HANDLE_ENTRY handleEntry = GDIOBJ_iGetHandleEntryForIndex ((WORD) hObj & 0xffff);
307 PGDIOBJHDR objectHeader;
309 DPRINT("GDIOBJ_LockObj: hObj: %d, magic: %x, \n handleEntry: %x, mag %x\n", hObj, Magic, handleEntry, handleEntry->wMagic);
310 if (handleEntry == 0 || (handleEntry->wMagic != Magic && Magic != GO_MAGIC_DONTCARE )
311 || (handleEntry->hProcessId != (HANDLE)0xFFFFFFFF &&
312 handleEntry->hProcessId != PsGetCurrentProcessId ())){
313 DPRINT("GDIBOJ_LockObj failed for %d, magic: %d, reqMagic\n",(WORD) hObj & 0xffff, handleEntry->wMagic, Magic);
317 objectHeader = (PGDIOBJHDR) handleEntry->pObject;
318 ASSERT(objectHeader);
319 if( objectHeader->dwCount > 0 ){
320 DbgPrint("Caution! GDIOBJ_LockObj trying to lock object second time\n" );
321 DbgPrint("\t called from: %x\n", __builtin_return_address(0));
324 ExAcquireFastMutex(&RefCountHandling);
325 objectHeader->dwCount++;
326 ExReleaseFastMutex(&RefCountHandling);
327 return (PGDIOBJ)((PCHAR)objectHeader + sizeof(GDIOBJHDR));
331 * Lock multiple objects. Use this function when you need to lock multiple objects and some of them may be
332 * duplicates. You should use this function to avoid trying to lock the same object twice!
334 * \param pList pointer to the list that contains handles to the objects. You should set hObj and Magic fields.
335 * \param nObj number of objects to lock
336 * \return for each entry in pList this function sets pObj field to point to the object.
338 * \note this function uses an O(n^2) algoritm because we shouldn't need to call it with more than 3 or 4 objects.
340 BOOL GDIOBJ_LockMultipleObj( PGDIMULTILOCK pList, INT nObj )
344 //go through the list checking for duplicate objects
345 for( i = 0; i < nObj; i++ ){
346 (pList+i)->pObj = NULL;
347 for( j = 0; j < i; j++ ){
348 if( ((pList+i)->hObj == (pList+j)->hObj)
349 && ((pList+i)->Magic == (pList+j)->Magic) ){
350 //already locked, so just copy the pointer to the object
351 (pList+i)->pObj = (pList+j)->pObj;
355 if( (pList+i)->pObj == NULL ){
356 //object hasn't been locked, so lock it.
357 (pList+i)->pObj = GDIOBJ_LockObj( (pList+i)->hObj, (pList+i)->Magic );
364 * Release GDI object. Every object locked by GDIOBJ_LockObj() must be unlocked. You should unlock the object
365 * as soon as you don't need to have access to it's data.
367 * \param hObj Object handle
368 * \param Magic one of the magic numbers defined in \ref GDI Magic
370 * \note This function performs delayed cleanup. If the object is locked when GDI_FreeObj() is called
371 * then \em this function frees the object when reference count is zero.
373 * \todo Change synchronization algorithm.
375 BOOL GDIOBJ_UnlockObj( HGDIOBJ hObj, WORD Magic )
377 PGDI_HANDLE_ENTRY handleEntry = GDIOBJ_iGetHandleEntryForIndex ((WORD) hObj & 0xffff);
378 PGDIOBJHDR objectHeader;
380 DPRINT("GDIOBJ_UnlockObj: hObj: %d, magic: %x, \n handleEntry: %x\n", hObj, Magic, handleEntry);
381 if (handleEntry == 0 || (handleEntry->wMagic != Magic && Magic != GO_MAGIC_DONTCARE )
382 || (handleEntry->hProcessId != (HANDLE)0xFFFFFFFF &&
383 handleEntry->hProcessId != PsGetCurrentProcessId ())){
384 DPRINT( "GDIOBJ_UnLockObj: failed\n");
388 objectHeader = (PGDIOBJHDR) handleEntry->pObject;
389 ASSERT(objectHeader);
391 ExAcquireFastMutex(&RefCountHandling);
392 if( ( objectHeader->dwCount & ~0x80000000 ) == 0 ){
393 ExReleaseFastMutex(&RefCountHandling);
394 DPRINT( "GDIOBJ_UnLockObj: unlock object that is not locked\n" );
398 objectHeader = (PGDIOBJHDR) handleEntry->pObject;
399 ASSERT(objectHeader);
400 objectHeader->dwCount--;
402 if( objectHeader->dwCount == 0x80000000 ){
403 //delayed object release
404 objectHeader->dwCount = 0;
405 ExReleaseFastMutex(&RefCountHandling);
406 DPRINT("GDIOBJ_UnlockObj: delayed delete\n");
407 return GDIOBJ_FreeObj( hObj, Magic, GDIOBJFLAG_DEFAULT );
409 ExReleaseFastMutex(&RefCountHandling);
415 * Unlock multiple objects. Use this function when you need to unlock multiple objects and some of them may be
418 * \param pList pointer to the list that contains handles to the objects. You should set hObj and Magic fields.
419 * \param nObj number of objects to lock
421 * \note this function uses O(n^2) algoritm because we shouldn't need to call it with more than 3 or 4 objects.
423 BOOL GDIOBJ_UnlockMultipleObj( PGDIMULTILOCK pList, INT nObj )
427 //go through the list checking for duplicate objects
428 for( i = 0; i < nObj; i++ ){
429 if( (pList+i)->pObj != NULL ){
430 for( j = i+1; j < nObj; j++ ){
431 if( ((pList+i)->pObj == (pList+j)->pObj) ){
432 //set the pointer to zero for all duplicates
433 (pList+j)->pObj = NULL;
436 GDIOBJ_UnlockObj( (pList+i)->hObj, (pList+i)->Magic );
437 (pList+i)->pObj = NULL;
444 * Marks the object as global. (Creator process ID is set to 0xFFFFFFFF). Global objects may be
445 * accessed by any process.
446 * \param ObjectHandle - handle of the object to make global.
448 * \note Only stock objects should be marked global.
450 VOID GDIOBJ_MarkObjectGlobal(HGDIOBJ ObjectHandle)
452 PGDI_HANDLE_ENTRY handleEntry;
454 if (ObjectHandle == NULL)
457 handleEntry = GDIOBJ_iGetHandleEntryForIndex ((WORD)ObjectHandle & 0xffff);
458 if (handleEntry == 0)
461 handleEntry->hProcessId = (HANDLE)0xFFFFFFFF;
465 * Get the type (magic value) of the object.
466 * \param ObjectHandle - handle of the object.
467 * \return GDI Magic value.
469 WORD GDIOBJ_GetHandleMagic (HGDIOBJ ObjectHandle)
471 PGDI_HANDLE_ENTRY handleEntry;
473 if (ObjectHandle == NULL)
476 handleEntry = GDIOBJ_iGetHandleEntryForIndex ((WORD)ObjectHandle & 0xffff);
477 if (handleEntry == 0 ||
478 (handleEntry->hProcessId != (HANDLE)0xFFFFFFFF &&
479 handleEntry->hProcessId != PsGetCurrentProcessId ()))
482 return handleEntry->wMagic;
486 * Initialization of the GDI object engine.
489 InitGdiObjectHandleTable (void)
491 DPRINT ("InitGdiObjectHandleTable\n");
492 ExInitializeFastMutex (&HandleTableMutex);
493 ExInitializeFastMutex (&RefCountHandling);
495 HandleTable = GDIOBJ_iAllocHandleTable (GDI_HANDLE_NUMBER);
496 DPRINT("HandleTable: %x\n", HandleTable );
498 InitEngHandleTable();
502 * Creates a bunch of stock objects: brushes, pens, fonts.
504 VOID CreateStockObjects(void)
506 // Create GDI Stock Objects from the logical structures we've defined
508 StockObjects[WHITE_BRUSH] = W32kCreateBrushIndirect(&WhiteBrush);
509 GDIOBJ_MarkObjectGlobal(StockObjects[WHITE_BRUSH]);
510 StockObjects[LTGRAY_BRUSH] = W32kCreateBrushIndirect(&LtGrayBrush);
511 GDIOBJ_MarkObjectGlobal(StockObjects[LTGRAY_BRUSH]);
512 StockObjects[GRAY_BRUSH] = W32kCreateBrushIndirect(&GrayBrush);
513 GDIOBJ_MarkObjectGlobal(StockObjects[GRAY_BRUSH]);
514 StockObjects[DKGRAY_BRUSH] = W32kCreateBrushIndirect(&DkGrayBrush);
515 GDIOBJ_MarkObjectGlobal(StockObjects[DKGRAY_BRUSH]);
516 StockObjects[BLACK_BRUSH] = W32kCreateBrushIndirect(&BlackBrush);
517 GDIOBJ_MarkObjectGlobal(StockObjects[BLACK_BRUSH]);
518 StockObjects[NULL_BRUSH] = W32kCreateBrushIndirect(&NullBrush);
519 GDIOBJ_MarkObjectGlobal(StockObjects[NULL_BRUSH]);
521 StockObjects[WHITE_PEN] = W32kCreatePenIndirect(&WhitePen);
522 GDIOBJ_MarkObjectGlobal(StockObjects[WHITE_PEN]);
523 StockObjects[BLACK_PEN] = W32kCreatePenIndirect(&BlackPen);
524 GDIOBJ_MarkObjectGlobal(StockObjects[BLACK_PEN]);
525 StockObjects[NULL_PEN] = W32kCreatePenIndirect(&NullPen);
526 GDIOBJ_MarkObjectGlobal(StockObjects[NULL_PEN]);
528 (void) TextIntCreateFontIndirect(&OEMFixedFont, &StockObjects[OEM_FIXED_FONT]);
529 GDIOBJ_MarkObjectGlobal(StockObjects[OEM_FIXED_FONT]);
530 (void) TextIntCreateFontIndirect(&AnsiFixedFont, &StockObjects[ANSI_FIXED_FONT]);
531 GDIOBJ_MarkObjectGlobal(StockObjects[ANSI_FIXED_FONT]);
532 (void) TextIntCreateFontIndirect(&SystemFont, &StockObjects[SYSTEM_FONT]);
533 GDIOBJ_MarkObjectGlobal(StockObjects[SYSTEM_FONT]);
534 (void) TextIntCreateFontIndirect(&DeviceDefaultFont, &StockObjects[DEVICE_DEFAULT_FONT]);
535 GDIOBJ_MarkObjectGlobal(StockObjects[DEVICE_DEFAULT_FONT]);
536 (void) TextIntCreateFontIndirect(&SystemFixedFont, &StockObjects[SYSTEM_FIXED_FONT]);
537 GDIOBJ_MarkObjectGlobal(StockObjects[SYSTEM_FIXED_FONT]);
538 (void) TextIntCreateFontIndirect(&DefaultGuiFont, &StockObjects[DEFAULT_GUI_FONT]);
539 GDIOBJ_MarkObjectGlobal(StockObjects[DEFAULT_GUI_FONT]);
541 StockObjects[DEFAULT_PALETTE] = (HGDIOBJ*)PALETTE_Init();
545 * Return stock object.
546 * \param Object - stock object id.
547 * \return Handle to the object.
549 HGDIOBJ STDCALL W32kGetStockObject(INT Object)
551 // check when adding new objects
552 if( (Object < 0) || (Object >= NB_STOCK_OBJECTS) )
554 return StockObjects[Object];
559 * \param hObject object handle
560 * \return if the function fails the returned value is NULL.
562 BOOL STDCALL W32kDeleteObject(HGDIOBJ hObject)
564 return GDIOBJ_FreeObj( hObject, GO_MAGIC_DONTCARE, GDIOBJFLAG_DEFAULT );
568 * Internal function. Called when the process is destroyed to free the remaining GDI handles.
569 * \param Process - PID of the process that was destroyed.
571 BOOL STDCALL W32kCleanupForProcess( INT Process )
574 PGDI_HANDLE_ENTRY handleEntry;
575 PGDIOBJHDR objectHeader;
577 for( i=1; i < GDI_HANDLE_NUMBER; i++ ){
578 handleEntry = GDIOBJ_iGetHandleEntryForIndex ((WORD) i & 0xffff);
579 if( handleEntry && handleEntry->wMagic != 0 && handleEntry->hProcessId == Process){
580 objectHeader = (PGDIOBJHDR) handleEntry->pObject;
581 DPRINT("\nW32kCleanup: %d, magic: %x \n process: %d, locks: %d", i, handleEntry->wMagic, handleEntry->hProcessId, objectHeader->dwCount);
582 GDIOBJ_FreeObj( (WORD) i & 0xffff, GO_MAGIC_DONTCARE, GDIOBJFLAG_IGNOREPID|GDIOBJFLAG_IGNORELOCK );
589 * Internal function. Dumps all the objects for the given process.
590 * \param If process == 0 dump all the objects.
593 VOID STDCALL W32kDumpGdiObjects( INT Process )
596 PGDI_HANDLE_ENTRY handleEntry;
597 PGDIOBJHDR objectHeader;
599 for( i=1; i < GDI_HANDLE_NUMBER; i++ ){
600 handleEntry = GDIOBJ_iGetHandleEntryForIndex ((WORD) i & 0xffff);
601 if( handleEntry && handleEntry->wMagic != 0 ){
602 objectHeader = (PGDIOBJHDR) handleEntry->pObject;
603 DPRINT("\nHandle: %d, magic: %x \n process: %d, locks: %d", i, handleEntry->wMagic, handleEntry->hProcessId, objectHeader->dwCount);