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.25 2003/05/29 13:18:39 gvg Exp $
26 #undef WIN32_LEAN_AND_MEAN
28 #include <ddk/ntddk.h>
29 #include <include/dce.h>
30 #include <include/object.h>
31 #include <win32k/gdiobj.h>
32 #include <win32k/brush.h>
33 #include <win32k/pen.h>
34 #include <win32k/text.h>
35 #include <win32k/dc.h>
36 #include <win32k/bitmaps.h>
37 #include <win32k/region.h>
38 #include <include/palette.h>
40 #include <win32k/debug1.h>
44 static LOGBRUSH WhiteBrush
=
45 { BS_SOLID
, RGB(255,255,255), 0 };
47 static LOGBRUSH LtGrayBrush
=
48 /* FIXME : this should perhaps be BS_HATCHED, at least for 1 bitperpixel */
49 { BS_SOLID
, RGB(192,192,192), 0 };
51 static LOGBRUSH GrayBrush
=
52 /* FIXME : this should perhaps be BS_HATCHED, at least for 1 bitperpixel */
53 { BS_SOLID
, RGB(128,128,128), 0 };
55 static LOGBRUSH DkGrayBrush
=
56 /* This is BS_HATCHED, for 1 bitperpixel. This makes the spray work in pbrush */
57 /* NB_HATCH_STYLES is an index into HatchBrushes */
58 { BS_HATCHED
, RGB(0,0,0), NB_HATCH_STYLES
};
60 static LOGBRUSH BlackBrush
=
61 { BS_SOLID
, RGB(0,0,0), 0 };
63 static LOGBRUSH NullBrush
=
66 static LOGPEN WhitePen
=
67 { PS_SOLID
, { 0, 0 }, RGB(255,255,255) };
69 static LOGPEN BlackPen
=
70 { PS_SOLID
, { 0, 0 }, RGB(0,0,0) };
72 static LOGPEN NullPen
=
73 { PS_NULL
, { 0, 0 }, 0 };
75 static LOGFONTW OEMFixedFont
=
76 { 14, 0, 0, 0, FW_NORMAL
, FALSE
, FALSE
, FALSE
, OEM_CHARSET
,
77 0, 0, DEFAULT_QUALITY
, FIXED_PITCH
| FF_MODERN
, L
"" };
79 /* Filler to make the location counter dword aligned again. This is necessary
80 since (a) LOGFONT is packed, (b) gcc places initialised variables in the code
81 segment, and (c) Solaris assembler is stupid. */
82 static UINT align_OEMFixedFont
= 1;
84 static LOGFONTW AnsiFixedFont
=
85 { 14, 0, 0, 0, FW_NORMAL
, FALSE
, FALSE
, FALSE
, ANSI_CHARSET
,
86 0, 0, DEFAULT_QUALITY
, FIXED_PITCH
| FF_MODERN
, L
"" };
88 static UINT align_AnsiFixedFont
= 1;
90 static LOGFONTW AnsiVarFont
=
91 { 14, 0, 0, 0, FW_NORMAL
, FALSE
, FALSE
, FALSE
, ANSI_CHARSET
,
92 0, 0, DEFAULT_QUALITY
, VARIABLE_PITCH
| FF_SWISS
, L
"MS Sans Serif" };
94 static UINT align_AnsiVarFont
= 1;
96 static LOGFONTW SystemFont
=
97 { 14, 0, 0, 0, FW_NORMAL
, FALSE
, FALSE
, FALSE
, ANSI_CHARSET
,
98 0, 0, DEFAULT_QUALITY
, VARIABLE_PITCH
| FF_SWISS
, L
"System" };
100 static UINT align_SystemFont
= 1;
102 static LOGFONTW DeviceDefaultFont
=
103 { 14, 0, 0, 0, FW_NORMAL
, FALSE
, FALSE
, FALSE
, ANSI_CHARSET
,
104 0, 0, DEFAULT_QUALITY
, VARIABLE_PITCH
| FF_SWISS
, L
"" };
106 static UINT align_DeviceDefaultFont
= 1;
108 static LOGFONTW SystemFixedFont
=
109 { 14, 0, 0, 0, FW_NORMAL
, FALSE
, FALSE
, FALSE
, ANSI_CHARSET
,
110 0, 0, DEFAULT_QUALITY
, FIXED_PITCH
| FF_MODERN
, L
"" };
112 static UINT align_SystemFixedFont
= 1;
114 /* FIXME: Is this correct? */
115 static LOGFONTW DefaultGuiFont
=
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 UINT align_DefaultGuiFont
= 1;
121 static HGDIOBJ
*StockObjects
[NB_STOCK_OBJECTS
]; // we dont assign these statically as WINE does because we might redesign
122 // the way handles work, so it's more dynamic now
125 HBITMAP hPseudoStockBitmap
; /*! 1x1 bitmap for memory DCs */
127 static PGDI_HANDLE_TABLE HandleTable
= 0;
128 static FAST_MUTEX HandleTableMutex
;
129 static FAST_MUTEX RefCountHandling
;
131 /*! Size of the GDI handle table
132 * per http://www.wd-mag.com/articles/1999/9902/9902b/9902b.htm?topic=articles
133 * gdi handle table can hold 0x4000 handles
135 #define GDI_HANDLE_NUMBER 0x4000
138 * Allocate GDI object table.
139 * \param Size - number of entries in the object table.
141 static PGDI_HANDLE_TABLE FASTCALL
142 GDIOBJ_iAllocHandleTable (WORD Size
)
144 PGDI_HANDLE_TABLE handleTable
;
146 ExAcquireFastMutexUnsafe (&HandleTableMutex
);
147 handleTable
= ExAllocatePool(PagedPool
,
148 sizeof (GDI_HANDLE_TABLE
) +
149 sizeof (GDI_HANDLE_ENTRY
) * Size
);
150 ASSERT( handleTable
);
153 sizeof (GDI_HANDLE_TABLE
) + sizeof (GDI_HANDLE_ENTRY
) * Size
);
154 handleTable
->wTableSize
= Size
;
155 ExReleaseFastMutexUnsafe (&HandleTableMutex
);
161 * Returns the entry into the handle table by index.
163 static PGDI_HANDLE_ENTRY FASTCALL
164 GDIOBJ_iGetHandleEntryForIndex (WORD TableIndex
)
166 //DPRINT("GDIOBJ_iGetHandleEntryForIndex: TableIndex: %d,\n handle: %x, ptr: %x\n", TableIndex, HandleTable->Handles [TableIndex], &(HandleTable->Handles [TableIndex]) );
167 //DPRINT("GIG: HandleTable: %x, Handles: %x, \n TableIndex: %x, pt: %x\n", HandleTable, HandleTable->Handles, TableIndex, ((PGDI_HANDLE_ENTRY)HandleTable->Handles+TableIndex));
168 //DPRINT("GIG: Hndl: %x, mag: %x\n", ((PGDI_HANDLE_ENTRY)HandleTable->Handles+TableIndex), ((PGDI_HANDLE_ENTRY)HandleTable->Handles+TableIndex)->wMagic);
169 return ((PGDI_HANDLE_ENTRY
)HandleTable
->Handles
+TableIndex
);
173 * Finds next free entry in the GDI handle table.
174 * \return index into the table is successful, zero otherwise.
177 GDIOBJ_iGetNextOpenHandleIndex (void)
181 ExAcquireFastMutexUnsafe (&HandleTableMutex
);
182 for (tableIndex
= 1; tableIndex
< HandleTable
->wTableSize
; tableIndex
++)
184 if (HandleTable
->Handles
[tableIndex
].wMagic
== 0)
186 HandleTable
->Handles
[tableIndex
].wMagic
= GO_MAGIC_DONTCARE
;
190 ExReleaseFastMutexUnsafe (&HandleTableMutex
);
192 return (tableIndex
< HandleTable
->wTableSize
) ? tableIndex
: 0;
196 * Allocate memory for GDI object and return handle to it.
198 * \param Size - size of the GDI object. This shouldn't to include the size of GDIOBJHDR.
199 * The actual amount of allocated memory is sizeof(GDIOBJHDR)+Size
200 * \param Magic - object magic (see GDI Magic)
202 * \return Handle of the allocated object.
204 * \note Use GDIOBJ_Lock() to obtain pointer to the new object.
206 HGDIOBJ FASTCALL
GDIOBJ_AllocObj(WORD Size
, WORD Magic
)
208 PGDIOBJHDR newObject
;
209 PGDI_HANDLE_ENTRY handleEntry
;
211 DPRINT("GDIOBJ_AllocObj: size: %d, magic: %x\n", Size
, Magic
);
212 newObject
= ExAllocatePool (PagedPool
, Size
+ sizeof (GDIOBJHDR
));
213 if (newObject
== NULL
)
215 DPRINT("GDIOBJ_AllocObj: failed\n");
218 RtlZeroMemory (newObject
, Size
+ sizeof (GDIOBJHDR
));
220 newObject
->wTableIndex
= GDIOBJ_iGetNextOpenHandleIndex ();
221 newObject
->dwCount
= 0;
222 handleEntry
= GDIOBJ_iGetHandleEntryForIndex (newObject
->wTableIndex
);
223 handleEntry
->wMagic
= Magic
;
224 handleEntry
->hProcessId
= PsGetCurrentProcessId ();
225 handleEntry
->pObject
= newObject
;
226 DPRINT("GDIOBJ_AllocObj: object handle %d\n", newObject
->wTableIndex
);
227 return (HGDIOBJ
) newObject
->wTableIndex
;
231 * Free memory allocated for the GDI object. For each object type this function calls the
232 * appropriate cleanup routine.
234 * \param hObj - handle of the object to be deleted.
235 * \param Magic - object magic or GO_MAGIC_DONTCARE.
236 * \param Flag - if set to GDIOBJFLAG_IGNOREPID then the routine doesn't check if the process that
237 * tries to delete the object is the same one that created it.
239 * \return Returns TRUE if succesful.
241 * \note You should only use GDIOBJFLAG_IGNOREPID if you are cleaning up after the process that terminated.
242 * \note This function deferres object deletion if it is still in use.
244 BOOL STDCALL
GDIOBJ_FreeObj(HGDIOBJ hObj
, WORD Magic
, DWORD Flag
)
246 PGDIOBJHDR objectHeader
;
247 PGDI_HANDLE_ENTRY handleEntry
;
251 handleEntry
= GDIOBJ_iGetHandleEntryForIndex ((WORD
)hObj
& 0xffff);
252 DPRINT("GDIOBJ_FreeObj: hObj: %d, magic: %x, handleEntry: %x\n", (WORD
)hObj
& 0xffff, Magic
, handleEntry
);
254 if (handleEntry
== 0 || (handleEntry
->wMagic
!= Magic
&& Magic
!= GO_MAGIC_DONTCARE
)
255 || ((handleEntry
->hProcessId
!= PsGetCurrentProcessId()) && !(Flag
& GDIOBJFLAG_IGNOREPID
))){
257 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
)) );
261 objectHeader
= (PGDIOBJHDR
) handleEntry
->pObject
;
262 ASSERT(objectHeader
);
263 DPRINT("FreeObj: locks: %x\n", objectHeader
->dwCount
);
264 if( !(Flag
& GDIOBJFLAG_IGNORELOCK
) ){
265 // check that the reference count is zero. if not then set flag
266 // and delete object when releaseobj is called
267 ExAcquireFastMutex(&RefCountHandling
);
268 if( ( objectHeader
->dwCount
& ~0x80000000 ) > 0 ){
269 DPRINT("GDIOBJ_FreeObj: delayed object deletion: count %d\n", objectHeader
->dwCount
);
270 objectHeader
->dwCount
|= 0x80000000;
271 ExReleaseFastMutex(&RefCountHandling
);
274 ExReleaseFastMutex(&RefCountHandling
);
277 //allow object to delete internal data
278 Obj
= (PGDIOBJ
)((PCHAR
)handleEntry
->pObject
+ sizeof(GDIOBJHDR
));
279 switch( handleEntry
->wMagic
){
280 case GO_REGION_MAGIC
:
281 bRet
= RGNDATA_InternalDelete( (PROSRGNDATA
) Obj
);
283 case GO_BITMAP_MAGIC
:
284 bRet
= Bitmap_InternalDelete( (PBITMAPOBJ
) Obj
);
287 bRet
= DC_InternalDeleteDC( (PDC
) Obj
);
290 case GO_PALETTE_MAGIC
:
291 case GO_DISABLED_DC_MAGIC
:
292 case GO_META_DC_MAGIC
:
293 case GO_METAFILE_MAGIC
:
294 case GO_METAFILE_DC_MAGIC
:
295 case GO_ENHMETAFILE_MAGIC
:
296 case GO_ENHMETAFILE_DC_MAGIC
:
302 bRet
= DCE_InternalDelete( (PDCE
) Obj
);
305 handleEntry
->hProcessId
= 0;
306 ExFreePool (handleEntry
->pObject
);
307 handleEntry
->pObject
= 0;
308 handleEntry
->wMagic
= 0;
314 * Return pointer to the object by handle.
316 * \param hObj Object handle
317 * \param Magic one of the magic numbers defined in \ref GDI Magic
318 * \return Pointer to the object.
320 * \note Process can only get pointer to the objects it created or global objects.
322 * \todo Don't allow to lock the objects twice! Synchronization!
324 PGDIOBJ FASTCALL
GDIOBJ_LockObj( HGDIOBJ hObj
, WORD Magic
)
326 PGDI_HANDLE_ENTRY handleEntry
= GDIOBJ_iGetHandleEntryForIndex ((WORD
) hObj
& 0xffff);
327 PGDIOBJHDR objectHeader
;
329 DPRINT("GDIOBJ_LockObj: hObj: %d, magic: %x, \n handleEntry: %x, mag %x\n", hObj
, Magic
, handleEntry
, handleEntry
->wMagic
);
330 if (handleEntry
== 0 || (handleEntry
->wMagic
!= Magic
&& Magic
!= GO_MAGIC_DONTCARE
)
331 || (handleEntry
->hProcessId
!= (HANDLE
)0xFFFFFFFF &&
332 handleEntry
->hProcessId
!= PsGetCurrentProcessId ())){
333 DPRINT("GDIBOJ_LockObj failed for %d, magic: %d, reqMagic\n",(WORD
) hObj
& 0xffff, handleEntry
->wMagic
, Magic
);
337 objectHeader
= (PGDIOBJHDR
) handleEntry
->pObject
;
338 ASSERT(objectHeader
);
339 if( objectHeader
->dwCount
> 0 ){
340 DbgPrint("Caution! GDIOBJ_LockObj trying to lock object second time\n" );
341 DbgPrint("\t called from: %x\n", __builtin_return_address(0));
344 ExAcquireFastMutex(&RefCountHandling
);
345 objectHeader
->dwCount
++;
346 ExReleaseFastMutex(&RefCountHandling
);
347 return (PGDIOBJ
)((PCHAR
)objectHeader
+ sizeof(GDIOBJHDR
));
351 * Lock multiple objects. Use this function when you need to lock multiple objects and some of them may be
352 * duplicates. You should use this function to avoid trying to lock the same object twice!
354 * \param pList pointer to the list that contains handles to the objects. You should set hObj and Magic fields.
355 * \param nObj number of objects to lock
356 * \return for each entry in pList this function sets pObj field to point to the object.
358 * \note this function uses an O(n^2) algoritm because we shouldn't need to call it with more than 3 or 4 objects.
360 BOOL FASTCALL
GDIOBJ_LockMultipleObj( PGDIMULTILOCK pList
, INT nObj
)
364 //go through the list checking for duplicate objects
365 for( i
= 0; i
< nObj
; i
++ ){
366 (pList
+i
)->pObj
= NULL
;
367 for( j
= 0; j
< i
; j
++ ){
368 if( ((pList
+i
)->hObj
== (pList
+j
)->hObj
)
369 && ((pList
+i
)->Magic
== (pList
+j
)->Magic
) ){
370 //already locked, so just copy the pointer to the object
371 (pList
+i
)->pObj
= (pList
+j
)->pObj
;
375 if( (pList
+i
)->pObj
== NULL
){
376 //object hasn't been locked, so lock it.
377 (pList
+i
)->pObj
= GDIOBJ_LockObj( (pList
+i
)->hObj
, (pList
+i
)->Magic
);
384 * Release GDI object. Every object locked by GDIOBJ_LockObj() must be unlocked. You should unlock the object
385 * as soon as you don't need to have access to it's data.
387 * \param hObj Object handle
388 * \param Magic one of the magic numbers defined in \ref GDI Magic
390 * \note This function performs delayed cleanup. If the object is locked when GDI_FreeObj() is called
391 * then \em this function frees the object when reference count is zero.
393 * \todo Change synchronization algorithm.
395 BOOL FASTCALL
GDIOBJ_UnlockObj( HGDIOBJ hObj
, WORD Magic
)
397 PGDI_HANDLE_ENTRY handleEntry
= GDIOBJ_iGetHandleEntryForIndex ((WORD
) hObj
& 0xffff);
398 PGDIOBJHDR objectHeader
;
400 DPRINT("GDIOBJ_UnlockObj: hObj: %d, magic: %x, \n handleEntry: %x\n", hObj
, Magic
, handleEntry
);
401 if (handleEntry
== 0 || (handleEntry
->wMagic
!= Magic
&& Magic
!= GO_MAGIC_DONTCARE
)
402 || (handleEntry
->hProcessId
!= (HANDLE
)0xFFFFFFFF &&
403 handleEntry
->hProcessId
!= PsGetCurrentProcessId ())){
404 DPRINT( "GDIOBJ_UnLockObj: failed\n");
408 objectHeader
= (PGDIOBJHDR
) handleEntry
->pObject
;
409 ASSERT(objectHeader
);
411 ExAcquireFastMutex(&RefCountHandling
);
412 if( ( objectHeader
->dwCount
& ~0x80000000 ) == 0 ){
413 ExReleaseFastMutex(&RefCountHandling
);
414 DPRINT( "GDIOBJ_UnLockObj: unlock object that is not locked\n" );
418 objectHeader
= (PGDIOBJHDR
) handleEntry
->pObject
;
419 ASSERT(objectHeader
);
420 objectHeader
->dwCount
--;
422 if( objectHeader
->dwCount
== 0x80000000 ){
423 //delayed object release
424 objectHeader
->dwCount
= 0;
425 ExReleaseFastMutex(&RefCountHandling
);
426 DPRINT("GDIOBJ_UnlockObj: delayed delete\n");
427 return GDIOBJ_FreeObj( hObj
, Magic
, GDIOBJFLAG_DEFAULT
);
429 ExReleaseFastMutex(&RefCountHandling
);
435 * Unlock multiple objects. Use this function when you need to unlock multiple objects and some of them may be
438 * \param pList pointer to the list that contains handles to the objects. You should set hObj and Magic fields.
439 * \param nObj number of objects to lock
441 * \note this function uses O(n^2) algoritm because we shouldn't need to call it with more than 3 or 4 objects.
443 BOOL FASTCALL
GDIOBJ_UnlockMultipleObj( PGDIMULTILOCK pList
, INT nObj
)
447 //go through the list checking for duplicate objects
448 for( i
= 0; i
< nObj
; i
++ ){
449 if( (pList
+i
)->pObj
!= NULL
){
450 for( j
= i
+1; j
< nObj
; j
++ ){
451 if( ((pList
+i
)->pObj
== (pList
+j
)->pObj
) ){
452 //set the pointer to zero for all duplicates
453 (pList
+j
)->pObj
= NULL
;
456 GDIOBJ_UnlockObj( (pList
+i
)->hObj
, (pList
+i
)->Magic
);
457 (pList
+i
)->pObj
= NULL
;
464 * Marks the object as global. (Creator process ID is set to 0xFFFFFFFF). Global objects may be
465 * accessed by any process.
466 * \param ObjectHandle - handle of the object to make global.
468 * \note Only stock objects should be marked global.
470 VOID FASTCALL
GDIOBJ_MarkObjectGlobal(HGDIOBJ ObjectHandle
)
472 PGDI_HANDLE_ENTRY handleEntry
;
474 if (ObjectHandle
== NULL
)
477 handleEntry
= GDIOBJ_iGetHandleEntryForIndex ((WORD
)ObjectHandle
& 0xffff);
478 if (handleEntry
== 0)
481 handleEntry
->hProcessId
= (HANDLE
)0xFFFFFFFF;
485 * Get the type (magic value) of the object.
486 * \param ObjectHandle - handle of the object.
487 * \return GDI Magic value.
489 WORD FASTCALL
GDIOBJ_GetHandleMagic (HGDIOBJ ObjectHandle
)
491 PGDI_HANDLE_ENTRY handleEntry
;
493 if (ObjectHandle
== NULL
)
496 handleEntry
= GDIOBJ_iGetHandleEntryForIndex ((WORD
)ObjectHandle
& 0xffff);
497 if (handleEntry
== 0 ||
498 (handleEntry
->hProcessId
!= (HANDLE
)0xFFFFFFFF &&
499 handleEntry
->hProcessId
!= PsGetCurrentProcessId ()))
502 return handleEntry
->wMagic
;
506 * Initialization of the GDI object engine.
509 InitGdiObjectHandleTable (VOID
)
511 DPRINT ("InitGdiObjectHandleTable\n");
512 ExInitializeFastMutex (&HandleTableMutex
);
513 ExInitializeFastMutex (&RefCountHandling
);
515 HandleTable
= GDIOBJ_iAllocHandleTable (GDI_HANDLE_NUMBER
);
516 DPRINT("HandleTable: %x\n", HandleTable
);
518 InitEngHandleTable();
522 * Creates a bunch of stock objects: brushes, pens, fonts.
524 VOID FASTCALL
CreateStockObjects(void)
526 // Create GDI Stock Objects from the logical structures we've defined
528 StockObjects
[WHITE_BRUSH
] = W32kCreateBrushIndirect(&WhiteBrush
);
529 GDIOBJ_MarkObjectGlobal(StockObjects
[WHITE_BRUSH
]);
530 StockObjects
[LTGRAY_BRUSH
] = W32kCreateBrushIndirect(&LtGrayBrush
);
531 GDIOBJ_MarkObjectGlobal(StockObjects
[LTGRAY_BRUSH
]);
532 StockObjects
[GRAY_BRUSH
] = W32kCreateBrushIndirect(&GrayBrush
);
533 GDIOBJ_MarkObjectGlobal(StockObjects
[GRAY_BRUSH
]);
534 StockObjects
[DKGRAY_BRUSH
] = W32kCreateBrushIndirect(&DkGrayBrush
);
535 GDIOBJ_MarkObjectGlobal(StockObjects
[DKGRAY_BRUSH
]);
536 StockObjects
[BLACK_BRUSH
] = W32kCreateBrushIndirect(&BlackBrush
);
537 GDIOBJ_MarkObjectGlobal(StockObjects
[BLACK_BRUSH
]);
538 StockObjects
[NULL_BRUSH
] = W32kCreateBrushIndirect(&NullBrush
);
539 GDIOBJ_MarkObjectGlobal(StockObjects
[NULL_BRUSH
]);
541 StockObjects
[WHITE_PEN
] = W32kCreatePenIndirect(&WhitePen
);
542 GDIOBJ_MarkObjectGlobal(StockObjects
[WHITE_PEN
]);
543 StockObjects
[BLACK_PEN
] = W32kCreatePenIndirect(&BlackPen
);
544 GDIOBJ_MarkObjectGlobal(StockObjects
[BLACK_PEN
]);
545 StockObjects
[NULL_PEN
] = W32kCreatePenIndirect(&NullPen
);
546 GDIOBJ_MarkObjectGlobal(StockObjects
[NULL_PEN
]);
548 (void) TextIntCreateFontIndirect(&OEMFixedFont
, &StockObjects
[OEM_FIXED_FONT
]);
549 GDIOBJ_MarkObjectGlobal(StockObjects
[OEM_FIXED_FONT
]);
550 (void) TextIntCreateFontIndirect(&AnsiFixedFont
, &StockObjects
[ANSI_FIXED_FONT
]);
551 GDIOBJ_MarkObjectGlobal(StockObjects
[ANSI_FIXED_FONT
]);
552 (void) TextIntCreateFontIndirect(&SystemFont
, &StockObjects
[SYSTEM_FONT
]);
553 GDIOBJ_MarkObjectGlobal(StockObjects
[SYSTEM_FONT
]);
554 (void) TextIntCreateFontIndirect(&DeviceDefaultFont
, &StockObjects
[DEVICE_DEFAULT_FONT
]);
555 GDIOBJ_MarkObjectGlobal(StockObjects
[DEVICE_DEFAULT_FONT
]);
556 (void) TextIntCreateFontIndirect(&SystemFixedFont
, &StockObjects
[SYSTEM_FIXED_FONT
]);
557 GDIOBJ_MarkObjectGlobal(StockObjects
[SYSTEM_FIXED_FONT
]);
558 (void) TextIntCreateFontIndirect(&DefaultGuiFont
, &StockObjects
[DEFAULT_GUI_FONT
]);
559 GDIOBJ_MarkObjectGlobal(StockObjects
[DEFAULT_GUI_FONT
]);
561 StockObjects
[DEFAULT_PALETTE
] = (HGDIOBJ
*)PALETTE_Init();
565 * Return stock object.
566 * \param Object - stock object id.
567 * \return Handle to the object.
569 HGDIOBJ STDCALL
W32kGetStockObject(INT Object
)
571 // check when adding new objects
572 if( (Object
< 0) || (Object
>= NB_STOCK_OBJECTS
) )
574 return StockObjects
[Object
];
579 * \param hObject object handle
580 * \return if the function fails the returned value is NULL.
582 BOOL STDCALL
W32kDeleteObject(HGDIOBJ hObject
)
584 return GDIOBJ_FreeObj( hObject
, GO_MAGIC_DONTCARE
, GDIOBJFLAG_DEFAULT
);
588 * Internal function. Called when the process is destroyed to free the remaining GDI handles.
589 * \param Process - PID of the process that was destroyed.
591 BOOL STDCALL
W32kCleanupForProcess( INT Process
)
594 PGDI_HANDLE_ENTRY handleEntry
;
595 PGDIOBJHDR objectHeader
;
597 for( i
=1; i
< GDI_HANDLE_NUMBER
; i
++ ){
598 handleEntry
= GDIOBJ_iGetHandleEntryForIndex ((WORD
) i
& 0xffff);
599 if( handleEntry
&& handleEntry
->wMagic
!= 0 && handleEntry
->hProcessId
== Process
){
600 objectHeader
= (PGDIOBJHDR
) handleEntry
->pObject
;
601 DPRINT("\nW32kCleanup: %d, magic: %x \n process: %d, locks: %d", i
, handleEntry
->wMagic
, handleEntry
->hProcessId
, objectHeader
->dwCount
);
602 GDIOBJ_FreeObj( (WORD
) i
& 0xffff, GO_MAGIC_DONTCARE
, GDIOBJFLAG_IGNOREPID
|GDIOBJFLAG_IGNORELOCK
);
609 * Internal function. Dumps all the objects for the given process.
610 * \param If process == 0 dump all the objects.
613 VOID STDCALL
W32kDumpGdiObjects( INT Process
)
616 PGDI_HANDLE_ENTRY handleEntry
;
617 PGDIOBJHDR objectHeader
;
619 for( i
=1; i
< GDI_HANDLE_NUMBER
; i
++ ){
620 handleEntry
= GDIOBJ_iGetHandleEntryForIndex ((WORD
) i
& 0xffff);
621 if( handleEntry
&& handleEntry
->wMagic
!= 0 ){
622 objectHeader
= (PGDIOBJHDR
) handleEntry
->pObject
;
623 DPRINT("\nHandle: %d, magic: %x \n process: %d, locks: %d", i
, handleEntry
->wMagic
, handleEntry
->hProcessId
, objectHeader
->dwCount
);