2 * GDIOBJ.C - GDI object manipulation routines
8 #undef WIN32_LEAN_AND_MEAN
10 #include <ddk/ntddk.h>
11 #include <win32k/gdiobj.h>
12 #include <win32k/brush.h>
13 #include <win32k/pen.h>
14 #include <win32k/text.h>
15 #include <win32k/dc.h>
16 #include <win32k/bitmaps.h>
17 #include <win32k/region.h>
19 #include <win32k/debug1.h>
23 static LOGBRUSH WhiteBrush =
24 { BS_SOLID, RGB(255,255,255), 0 };
26 static LOGBRUSH LtGrayBrush =
27 /* FIXME : this should perhaps be BS_HATCHED, at least for 1 bitperpixel */
28 { BS_SOLID, RGB(192,192,192), 0 };
30 static LOGBRUSH GrayBrush =
31 /* FIXME : this should perhaps be BS_HATCHED, at least for 1 bitperpixel */
32 { BS_SOLID, RGB(128,128,128), 0 };
34 static LOGBRUSH DkGrayBrush =
35 /* This is BS_HATCHED, for 1 bitperpixel. This makes the spray work in pbrush */
36 /* NB_HATCH_STYLES is an index into HatchBrushes */
37 { BS_HATCHED, RGB(0,0,0), NB_HATCH_STYLES };
39 static LOGBRUSH BlackBrush =
40 { BS_SOLID, RGB(0,0,0), 0 };
42 static LOGBRUSH NullBrush =
45 static LOGPEN WhitePen =
46 { PS_SOLID, { 0, 0 }, RGB(255,255,255) };
48 static LOGPEN BlackPen =
49 { PS_SOLID, { 0, 0 }, RGB(0,0,0) };
51 static LOGPEN NullPen =
52 { PS_NULL, { 0, 0 }, 0 };
54 static LOGFONT OEMFixedFont =
55 { 0, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, OEM_CHARSET,
56 0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN, L"" };
58 /* Filler to make the location counter dword aligned again. This is necessary
59 since (a) LOGFONT is packed, (b) gcc places initialised variables in the code
60 segment, and (c) Solaris assembler is stupid. */
61 static UINT align_OEMFixedFont = 1;
63 static LOGFONT AnsiFixedFont =
64 { 0, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
65 0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN, L"" };
67 static UINT align_AnsiFixedFont = 1;
69 static LOGFONT AnsiVarFont =
70 { 0, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
71 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS, L"MS Sans Serif" };
73 static UINT align_AnsiVarFont = 1;
75 static LOGFONT SystemFont =
76 { 0, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
77 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS, L"System" };
79 static UINT align_SystemFont = 1;
81 static LOGFONT DeviceDefaultFont =
82 { 0, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
83 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS, L"" };
85 static UINT align_DeviceDefaultFont = 1;
87 static LOGFONT SystemFixedFont =
88 { 0, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
89 0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN, L"" };
91 static UINT align_SystemFixedFont = 1;
93 /* FIXME: Is this correct? */
94 static LOGFONT DefaultGuiFont =
95 { 0, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
96 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS, L"MS Sans Serif" };
98 static UINT align_DefaultGuiFont = 1;
100 static HGDIOBJ *StockObjects[NB_STOCK_OBJECTS]; // we dont assign these statically as WINE does because we might redesign
101 // the way handles work, so it's more dynamic now
104 HBITMAP hPseudoStockBitmap; /*! 1x1 bitmap for memory DCs */
106 static PGDI_HANDLE_TABLE HandleTable = 0;
107 static FAST_MUTEX HandleTableMutex;
108 static FAST_MUTEX RefCountHandling;
110 /*! Size of the GDI handle table
111 * per http://www.wd-mag.com/articles/1999/9902/9902b/9902b.htm?topic=articles
112 * gdi handle table can hold 0x4000 handles
114 #define GDI_HANDLE_NUMBER 0x4000
117 * Allocate GDI object table.
118 * \param Size - number of entries in the object table.
120 static PGDI_HANDLE_TABLE
121 GDIOBJ_iAllocHandleTable (WORD Size)
123 PGDI_HANDLE_TABLE handleTable;
125 ExAcquireFastMutexUnsafe (&HandleTableMutex);
126 handleTable = ExAllocatePool(PagedPool,
127 sizeof (GDI_HANDLE_TABLE) +
128 sizeof (GDI_HANDLE_ENTRY) * Size);
129 ASSERT( handleTable );
132 sizeof (GDI_HANDLE_TABLE) + sizeof (GDI_HANDLE_ENTRY) * Size);
133 handleTable->wTableSize = Size;
134 ExReleaseFastMutexUnsafe (&HandleTableMutex);
140 * Returns the entry into the handle table by index.
142 static PGDI_HANDLE_ENTRY
143 GDIOBJ_iGetHandleEntryForIndex (WORD TableIndex)
145 //DPRINT("GDIOBJ_iGetHandleEntryForIndex: TableIndex: %d,\n handle: %x, ptr: %x\n", TableIndex, HandleTable->Handles [TableIndex], &(HandleTable->Handles [TableIndex]) );
146 //DPRINT("GIG: HandleTable: %x, Handles: %x, \n TableIndex: %x, pt: %x\n", HandleTable, HandleTable->Handles, TableIndex, ((PGDI_HANDLE_ENTRY)HandleTable->Handles+TableIndex));
147 //DPRINT("GIG: Hndl: %x, mag: %x\n", ((PGDI_HANDLE_ENTRY)HandleTable->Handles+TableIndex), ((PGDI_HANDLE_ENTRY)HandleTable->Handles+TableIndex)->wMagic);
148 return ((PGDI_HANDLE_ENTRY)HandleTable->Handles+TableIndex);
152 * Finds next free entry in the GDI handle table.
153 * \return index into the table is successful, zero otherwise.
156 GDIOBJ_iGetNextOpenHandleIndex (void)
160 ExAcquireFastMutexUnsafe (&HandleTableMutex);
161 for (tableIndex = 1; tableIndex < HandleTable->wTableSize; tableIndex++)
163 if (HandleTable->Handles [tableIndex].wMagic == 0)
165 HandleTable->Handles [tableIndex].wMagic = GO_MAGIC_DONTCARE;
169 ExReleaseFastMutexUnsafe (&HandleTableMutex);
171 return (tableIndex < HandleTable->wTableSize) ? tableIndex : 0;
175 * Allocate memory for GDI object and return handle to it.
177 * \param Size - size of the GDI object. This shouldn't to include the size of GDIOBJHDR.
178 * The actual amount of allocated memory is sizeof(GDIOBJHDR)+Size
179 * \param Magic - object magic (see GDI Magic)
181 * \return Handle of the allocated object.
183 * \note Use GDIOBJ_Lock() to obtain pointer to the new object.
185 HGDIOBJ GDIOBJ_AllocObj(WORD Size, WORD Magic)
187 PGDIOBJHDR newObject;
188 PGDI_HANDLE_ENTRY handleEntry;
190 DPRINT("GDIOBJ_AllocObj: size: %d, magic: %x\n", Size, Magic);
191 newObject = ExAllocatePool (PagedPool, Size + sizeof (GDIOBJHDR));
192 if (newObject == NULL)
194 DPRINT("GDIOBJ_AllocObj: failed\n");
197 RtlZeroMemory (newObject, Size + sizeof (GDIOBJHDR));
199 newObject->wTableIndex = GDIOBJ_iGetNextOpenHandleIndex ();
200 newObject->dwCount = 0;
201 handleEntry = GDIOBJ_iGetHandleEntryForIndex (newObject->wTableIndex);
202 handleEntry->wMagic = Magic;
203 handleEntry->hProcessId = PsGetCurrentProcessId ();
204 handleEntry->pObject = newObject;
205 DPRINT("GDIOBJ_AllocObj: object handle %d\n", newObject->wTableIndex );
206 return (HGDIOBJ) newObject->wTableIndex;
210 * Free memory allocated for the GDI object. For each object type this function calls the
211 * appropriate cleanup routine.
213 * \param hObj - handle of the object to be deleted.
214 * \param Magic - object magic or GO_MAGIC_DONTCARE.
215 * \param Flag - if set to GDIOBJFLAG_IGNOREPID then the routine doesn't check if the process that
216 * tries to delete the object is the same one that created it.
218 * \return Returns TRUE if succesful.
220 * \note You should only use GDIOBJFLAG_IGNOREPID if you are cleaning up after the process that terminated.
221 * \note This function deferres object deletion if it is still in use.
223 BOOL GDIOBJ_FreeObj(HGDIOBJ hObj, WORD Magic, DWORD Flag)
225 PGDIOBJHDR objectHeader;
226 PGDI_HANDLE_ENTRY handleEntry;
230 handleEntry = GDIOBJ_iGetHandleEntryForIndex ((WORD)hObj & 0xffff);
231 DPRINT("GDIOBJ_FreeObj: hObj: %d, magic: %x, handleEntry: %x\n", (WORD)hObj & 0xffff, Magic, handleEntry );
233 if (handleEntry == 0 || (handleEntry->wMagic != Magic && Magic != GO_MAGIC_DONTCARE )
234 || ((handleEntry->hProcessId != PsGetCurrentProcessId()) && !(Flag & GDIOBJFLAG_IGNOREPID))){
236 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)) );
240 objectHeader = (PGDIOBJHDR) handleEntry->pObject;
241 ASSERT(objectHeader);
242 DPRINT("FreeObj: locks: %x\n", objectHeader->dwCount );
243 if( !(Flag & GDIOBJFLAG_IGNORELOCK) ){
244 // check that the reference count is zero. if not then set flag
245 // and delete object when releaseobj is called
246 ExAcquireFastMutex(&RefCountHandling);
247 if( ( objectHeader->dwCount & ~0x80000000 ) > 0 ){
248 DPRINT("GDIOBJ_FreeObj: delayed object deletion: count %d\n", objectHeader->dwCount);
249 objectHeader->dwCount |= 0x80000000;
250 ExReleaseFastMutex(&RefCountHandling);
253 ExReleaseFastMutex(&RefCountHandling);
256 //allow object to delete internal data
257 Obj = (PGDIOBJ)((PCHAR)handleEntry->pObject + sizeof(GDIOBJHDR));
258 switch( handleEntry->wMagic ){
259 case GO_REGION_MAGIC:
260 bRet = RGNDATA_InternalDelete( (PROSRGNDATA) Obj );
262 case GO_BITMAP_MAGIC:
263 bRet = Bitmap_InternalDelete( (PBITMAPOBJ) Obj );
266 bRet = DC_InternalDeleteDC( (PDC) Obj );
269 case GO_PALETTE_MAGIC:
270 case GO_DISABLED_DC_MAGIC:
271 case GO_META_DC_MAGIC:
272 case GO_METAFILE_MAGIC:
273 case GO_METAFILE_DC_MAGIC:
274 case GO_ENHMETAFILE_MAGIC:
275 case GO_ENHMETAFILE_DC_MAGIC:
281 handleEntry->hProcessId = 0;
282 ExFreePool (handleEntry->pObject);
283 handleEntry->pObject = 0;
284 handleEntry->wMagic = 0;
290 * Return pointer to the object by handle.
292 * \param hObj Object handle
293 * \param Magic one of the magic numbers defined in \ref GDI Magic
294 * \return Pointer to the object.
296 * \note Process can only get pointer to the objects it created or global objects.
298 * \todo Don't allow to lock the objects twice! Synchronization!
300 PGDIOBJ GDIOBJ_LockObj( HGDIOBJ hObj, WORD Magic )
302 PGDI_HANDLE_ENTRY handleEntry = GDIOBJ_iGetHandleEntryForIndex ((WORD) hObj & 0xffff);
303 PGDIOBJHDR objectHeader;
305 DPRINT("GDIOBJ_LockObj: hObj: %d, magic: %x, \n handleEntry: %x, mag %x\n", hObj, Magic, handleEntry, handleEntry->wMagic);
306 if (handleEntry == 0 || (handleEntry->wMagic != Magic && Magic != GO_MAGIC_DONTCARE )
307 || (handleEntry->hProcessId != (HANDLE)0xFFFFFFFF &&
308 handleEntry->hProcessId != PsGetCurrentProcessId ())){
309 DPRINT("GDIBOJ_LockObj failed for %d, magic: %d, reqMagic\n",(WORD) hObj & 0xffff, handleEntry->wMagic, Magic);
313 objectHeader = (PGDIOBJHDR) handleEntry->pObject;
314 ASSERT(objectHeader);
315 if( objectHeader->dwCount > 0 ){
316 DbgPrint("Caution! GDIOBJ_LockObj trying to lock object second time\n" );
317 DbgPrint("\t called from: %x\n", __builtin_return_address(0));
320 ExAcquireFastMutex(&RefCountHandling);
321 objectHeader->dwCount++;
322 ExReleaseFastMutex(&RefCountHandling);
323 return (PGDIOBJ)((PCHAR)objectHeader + sizeof(GDIOBJHDR));
327 * Lock multiple objects. Use this function when you need to lock multiple objects and some of them may be
328 * duplicates. You should use this function to avoid trying to lock the same object twice!
330 * \param pList pointer to the list that contains handles to the objects. You should set hObj and Magic fields.
331 * \param nObj number of objects to lock
332 * \return for each entry in pList this function sets pObj field to point to the object.
334 * \note this function uses an O(n^2) algoritm because we shouldn't need to call it with more than 3 or 4 objects.
336 BOOL GDIOBJ_LockMultipleObj( PGDIMULTILOCK pList, INT nObj )
340 //go through the list checking for duplicate objects
341 for( i = 0; i < nObj; i++ ){
342 (pList+i)->pObj = NULL;
343 for( j = 0; j < i; j++ ){
344 if( ((pList+i)->hObj == (pList+j)->hObj)
345 && ((pList+i)->Magic == (pList+j)->Magic) ){
346 //already locked, so just copy the pointer to the object
347 (pList+i)->pObj = (pList+j)->pObj;
351 if( (pList+i)->pObj == NULL ){
352 //object hasn't been locked, so lock it.
353 (pList+i)->pObj = GDIOBJ_LockObj( (pList+i)->hObj, (pList+i)->Magic );
360 * Release GDI object. Every object locked by GDIOBJ_LockObj() must be unlocked. You should unlock the object
361 * as soon as you don't need to have access to it's data.
363 * \param hObj Object handle
364 * \param Magic one of the magic numbers defined in \ref GDI Magic
366 * \note This function performs delayed cleanup. If the object is locked when GDI_FreeObj() is called
367 * then \em this function frees the object when reference count is zero.
369 * \todo Change synchronization algorithm.
371 BOOL GDIOBJ_UnlockObj( HGDIOBJ hObj, WORD Magic )
373 PGDI_HANDLE_ENTRY handleEntry = GDIOBJ_iGetHandleEntryForIndex ((WORD) hObj & 0xffff);
374 PGDIOBJHDR objectHeader;
376 DPRINT("GDIOBJ_UnlockObj: hObj: %d, magic: %x, \n handleEntry: %x\n", hObj, Magic, handleEntry);
377 if (handleEntry == 0 || (handleEntry->wMagic != Magic && Magic != GO_MAGIC_DONTCARE )
378 || (handleEntry->hProcessId != (HANDLE)0xFFFFFFFF &&
379 handleEntry->hProcessId != PsGetCurrentProcessId ())){
380 DPRINT( "GDIOBJ_UnLockObj: failed\n");
384 objectHeader = (PGDIOBJHDR) handleEntry->pObject;
385 ASSERT(objectHeader);
387 ExAcquireFastMutex(&RefCountHandling);
388 if( ( objectHeader->dwCount & ~0x80000000 ) == 0 ){
389 ExReleaseFastMutex(&RefCountHandling);
390 DPRINT( "GDIOBJ_UnLockObj: unlock object that is not locked\n" );
394 objectHeader = (PGDIOBJHDR) handleEntry->pObject;
395 ASSERT(objectHeader);
396 objectHeader->dwCount--;
398 if( objectHeader->dwCount == 0x80000000 ){
399 //delayed object release
400 objectHeader->dwCount = 0;
401 ExReleaseFastMutex(&RefCountHandling);
402 DPRINT("GDIOBJ_UnlockObj: delayed delete\n");
403 return GDIOBJ_FreeObj( hObj, Magic, GDIOBJFLAG_DEFAULT );
405 ExReleaseFastMutex(&RefCountHandling);
411 * Unlock multiple objects. Use this function when you need to unlock multiple objects and some of them may be
414 * \param pList pointer to the list that contains handles to the objects. You should set hObj and Magic fields.
415 * \param nObj number of objects to lock
417 * \note this function uses O(n^2) algoritm because we shouldn't need to call it with more than 3 or 4 objects.
419 BOOL GDIOBJ_UnlockMultipleObj( PGDIMULTILOCK pList, INT nObj )
423 //go through the list checking for duplicate objects
424 for( i = 0; i < nObj; i++ ){
425 if( (pList+i)->pObj != NULL ){
426 for( j = i+1; j < nObj; j++ ){
427 if( ((pList+i)->pObj == (pList+j)->pObj) ){
428 //set the pointer to zero for all duplicates
429 (pList+j)->pObj = NULL;
432 GDIOBJ_UnlockObj( (pList+i)->hObj, (pList+i)->Magic );
433 (pList+i)->pObj = NULL;
440 * Marks the object as global. (Creator process ID is set to 0xFFFFFFFF). Global objects may be
441 * accessed by any process.
442 * \param ObjectHandle - handle of the object to make global.
444 * \note Only stock objects should be marked global.
446 VOID GDIOBJ_MarkObjectGlobal(HGDIOBJ ObjectHandle)
448 PGDI_HANDLE_ENTRY handleEntry;
450 if (ObjectHandle == NULL)
453 handleEntry = GDIOBJ_iGetHandleEntryForIndex ((WORD)ObjectHandle & 0xffff);
454 if (handleEntry == 0)
457 handleEntry->hProcessId = (HANDLE)0xFFFFFFFF;
461 * Get the type (magic value) of the object.
462 * \param ObjectHandle - handle of the object.
463 * \return GDI Magic value.
465 WORD GDIOBJ_GetHandleMagic (HGDIOBJ ObjectHandle)
467 PGDI_HANDLE_ENTRY handleEntry;
469 if (ObjectHandle == NULL)
472 handleEntry = GDIOBJ_iGetHandleEntryForIndex ((WORD)ObjectHandle & 0xffff);
473 if (handleEntry == 0 ||
474 (handleEntry->hProcessId != (HANDLE)0xFFFFFFFF &&
475 handleEntry->hProcessId != PsGetCurrentProcessId ()))
478 return handleEntry->wMagic;
482 * Initialization of the GDI object engine.
485 InitGdiObjectHandleTable (void)
487 DPRINT ("InitGdiObjectHandleTable\n");
488 ExInitializeFastMutex (&HandleTableMutex);
489 ExInitializeFastMutex (&RefCountHandling);
491 HandleTable = GDIOBJ_iAllocHandleTable (GDI_HANDLE_NUMBER);
492 DPRINT("HandleTable: %x\n", HandleTable );
494 InitEngHandleTable();
498 * Creates a bunch of stock objects: brushes, pens, fonts.
500 VOID CreateStockObjects(void)
502 // Create GDI Stock Objects from the logical structures we've defined
504 StockObjects[WHITE_BRUSH] = W32kCreateBrushIndirect(&WhiteBrush);
505 GDIOBJ_MarkObjectGlobal(StockObjects[WHITE_BRUSH]);
506 StockObjects[LTGRAY_BRUSH] = W32kCreateBrushIndirect(&LtGrayBrush);
507 GDIOBJ_MarkObjectGlobal(StockObjects[LTGRAY_BRUSH]);
508 StockObjects[GRAY_BRUSH] = W32kCreateBrushIndirect(&GrayBrush);
509 GDIOBJ_MarkObjectGlobal(StockObjects[GRAY_BRUSH]);
510 StockObjects[DKGRAY_BRUSH] = W32kCreateBrushIndirect(&DkGrayBrush);
511 GDIOBJ_MarkObjectGlobal(StockObjects[DKGRAY_BRUSH]);
512 StockObjects[BLACK_BRUSH] = W32kCreateBrushIndirect(&BlackBrush);
513 GDIOBJ_MarkObjectGlobal(StockObjects[BLACK_BRUSH]);
514 StockObjects[NULL_BRUSH] = W32kCreateBrushIndirect(&NullBrush);
515 GDIOBJ_MarkObjectGlobal(StockObjects[NULL_BRUSH]);
517 StockObjects[WHITE_PEN] = W32kCreatePenIndirect(&WhitePen);
518 GDIOBJ_MarkObjectGlobal(StockObjects[WHITE_PEN]);
519 StockObjects[BLACK_PEN] = W32kCreatePenIndirect(&BlackPen);
520 GDIOBJ_MarkObjectGlobal(StockObjects[BLACK_PEN]);
521 StockObjects[NULL_PEN] = W32kCreatePenIndirect(&NullPen);
522 GDIOBJ_MarkObjectGlobal(StockObjects[NULL_PEN]);
524 StockObjects[OEM_FIXED_FONT] = W32kCreateFontIndirect(&OEMFixedFont);
525 GDIOBJ_MarkObjectGlobal(StockObjects[OEM_FIXED_FONT]);
526 StockObjects[ANSI_FIXED_FONT] = W32kCreateFontIndirect(&AnsiFixedFont);
527 GDIOBJ_MarkObjectGlobal(StockObjects[ANSI_FIXED_FONT]);
528 StockObjects[SYSTEM_FONT] = W32kCreateFontIndirect(&SystemFont);
529 GDIOBJ_MarkObjectGlobal(StockObjects[SYSTEM_FONT]);
530 StockObjects[DEVICE_DEFAULT_FONT] =
531 W32kCreateFontIndirect(&DeviceDefaultFont);
532 GDIOBJ_MarkObjectGlobal(StockObjects[DEVICE_DEFAULT_FONT]);
533 StockObjects[SYSTEM_FIXED_FONT] = W32kCreateFontIndirect(&SystemFixedFont);
534 GDIOBJ_MarkObjectGlobal(StockObjects[SYSTEM_FIXED_FONT]);
535 StockObjects[DEFAULT_GUI_FONT] = W32kCreateFontIndirect(&DefaultGuiFont);
536 GDIOBJ_MarkObjectGlobal(StockObjects[DEFAULT_GUI_FONT]);
538 StockObjects[DEFAULT_PALETTE] = (HGDIOBJ*)PALETTE_Init();
542 * Return stock object.
543 * \param Object - stock object id.
544 * \return Handle to the object.
546 HGDIOBJ STDCALL W32kGetStockObject(INT Object)
548 // check when adding new objects
549 if( (Object < 0) || (Object >= NB_STOCK_OBJECTS) )
551 return StockObjects[Object];
556 * \param hObject object handle
557 * \return if the function fails the returned value is NULL.
559 BOOL STDCALL W32kDeleteObject(HGDIOBJ hObject)
561 return GDIOBJ_FreeObj( hObject, GO_MAGIC_DONTCARE, GDIOBJFLAG_DEFAULT );
565 * Internal function. Called when the process is destroyed to free the remaining GDI handles.
566 * \param Process - PID of the process that was destroyed.
568 BOOL STDCALL W32kCleanupForProcess( INT Process )
571 PGDI_HANDLE_ENTRY handleEntry;
572 PGDIOBJHDR objectHeader;
574 for( i=1; i < GDI_HANDLE_NUMBER; i++ ){
575 handleEntry = GDIOBJ_iGetHandleEntryForIndex ((WORD) i & 0xffff);
576 if( handleEntry && handleEntry->wMagic != 0 && handleEntry->hProcessId == Process){
577 objectHeader = (PGDIOBJHDR) handleEntry->pObject;
578 DPRINT("\nW32kCleanup: %d, magic: %x \n process: %d, locks: %d", i, handleEntry->wMagic, handleEntry->hProcessId, objectHeader->dwCount);
579 GDIOBJ_FreeObj( (WORD) i & 0xffff, GO_MAGIC_DONTCARE, GDIOBJFLAG_IGNOREPID|GDIOBJFLAG_IGNORELOCK );
586 * Internal function. Dumps all the objects for the given process.
587 * \param If process == 0 dump all the objects.
590 VOID STDCALL W32kDumpGdiObjects( INT Process )
593 PGDI_HANDLE_ENTRY handleEntry;
594 PGDIOBJHDR objectHeader;
596 for( i=1; i < GDI_HANDLE_NUMBER; i++ ){
597 handleEntry = GDIOBJ_iGetHandleEntryForIndex ((WORD) i & 0xffff);
598 if( handleEntry && handleEntry->wMagic != 0 ){
599 objectHeader = (PGDIOBJHDR) handleEntry->pObject;
600 DPRINT("\nHandle: %d, magic: %x \n process: %d, locks: %d", i, handleEntry->wMagic, handleEntry->hProcessId, objectHeader->dwCount);