Set height of default fonts to non-zero
[reactos.git] / reactos / subsys / win32k / objects / gdiobj.c
1 /*
2 * ReactOS W32 Subsystem
3 * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
4 *
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.
9 *
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.
14 *
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.
18 */
19 /*
20 * GDIOBJ.C - GDI object manipulation routines
21 *
22 * $Id: gdiobj.c,v 1.25 2003/05/29 13:18:39 gvg Exp $
23 *
24 */
25
26 #undef WIN32_LEAN_AND_MEAN
27 #include <windows.h>
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>
39 #define NDEBUG
40 #include <win32k/debug1.h>
41
42 // GDI stock objects
43
44 static LOGBRUSH WhiteBrush =
45 { BS_SOLID, RGB(255,255,255), 0 };
46
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 };
50
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 };
54
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 };
59
60 static LOGBRUSH BlackBrush =
61 { BS_SOLID, RGB(0,0,0), 0 };
62
63 static LOGBRUSH NullBrush =
64 { BS_NULL, 0, 0 };
65
66 static LOGPEN WhitePen =
67 { PS_SOLID, { 0, 0 }, RGB(255,255,255) };
68
69 static LOGPEN BlackPen =
70 { PS_SOLID, { 0, 0 }, RGB(0,0,0) };
71
72 static LOGPEN NullPen =
73 { PS_NULL, { 0, 0 }, 0 };
74
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"" };
78
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;
83
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"" };
87
88 static UINT align_AnsiFixedFont = 1;
89
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" };
93
94 static UINT align_AnsiVarFont = 1;
95
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" };
99
100 static UINT align_SystemFont = 1;
101
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"" };
105
106 static UINT align_DeviceDefaultFont = 1;
107
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"" };
111
112 static UINT align_SystemFixedFont = 1;
113
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" };
118
119 static UINT align_DefaultGuiFont = 1;
120
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
123
124
125 HBITMAP hPseudoStockBitmap; /*! 1x1 bitmap for memory DCs */
126
127 static PGDI_HANDLE_TABLE HandleTable = 0;
128 static FAST_MUTEX HandleTableMutex;
129 static FAST_MUTEX RefCountHandling;
130
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
134 */
135 #define GDI_HANDLE_NUMBER 0x4000
136
137 /*!
138 * Allocate GDI object table.
139 * \param Size - number of entries in the object table.
140 */
141 static PGDI_HANDLE_TABLE FASTCALL
142 GDIOBJ_iAllocHandleTable (WORD Size)
143 {
144 PGDI_HANDLE_TABLE handleTable;
145
146 ExAcquireFastMutexUnsafe (&HandleTableMutex);
147 handleTable = ExAllocatePool(PagedPool,
148 sizeof (GDI_HANDLE_TABLE) +
149 sizeof (GDI_HANDLE_ENTRY) * Size);
150 ASSERT( handleTable );
151 memset (handleTable,
152 0,
153 sizeof (GDI_HANDLE_TABLE) + sizeof (GDI_HANDLE_ENTRY) * Size);
154 handleTable->wTableSize = Size;
155 ExReleaseFastMutexUnsafe (&HandleTableMutex);
156
157 return handleTable;
158 }
159
160 /*!
161 * Returns the entry into the handle table by index.
162 */
163 static PGDI_HANDLE_ENTRY FASTCALL
164 GDIOBJ_iGetHandleEntryForIndex (WORD TableIndex)
165 {
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);
170 }
171
172 /*!
173 * Finds next free entry in the GDI handle table.
174 * \return index into the table is successful, zero otherwise.
175 */
176 static WORD FASTCALL
177 GDIOBJ_iGetNextOpenHandleIndex (void)
178 {
179 WORD tableIndex;
180
181 ExAcquireFastMutexUnsafe (&HandleTableMutex);
182 for (tableIndex = 1; tableIndex < HandleTable->wTableSize; tableIndex++)
183 {
184 if (HandleTable->Handles [tableIndex].wMagic == 0)
185 {
186 HandleTable->Handles [tableIndex].wMagic = GO_MAGIC_DONTCARE;
187 break;
188 }
189 }
190 ExReleaseFastMutexUnsafe (&HandleTableMutex);
191
192 return (tableIndex < HandleTable->wTableSize) ? tableIndex : 0;
193 }
194
195 /*!
196 * Allocate memory for GDI object and return handle to it.
197 *
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)
201 *
202 * \return Handle of the allocated object.
203 *
204 * \note Use GDIOBJ_Lock() to obtain pointer to the new object.
205 */
206 HGDIOBJ FASTCALL GDIOBJ_AllocObj(WORD Size, WORD Magic)
207 {
208 PGDIOBJHDR newObject;
209 PGDI_HANDLE_ENTRY handleEntry;
210
211 DPRINT("GDIOBJ_AllocObj: size: %d, magic: %x\n", Size, Magic);
212 newObject = ExAllocatePool (PagedPool, Size + sizeof (GDIOBJHDR));
213 if (newObject == NULL)
214 {
215 DPRINT("GDIOBJ_AllocObj: failed\n");
216 return NULL;
217 }
218 RtlZeroMemory (newObject, Size + sizeof (GDIOBJHDR));
219
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;
228 }
229
230 /*!
231 * Free memory allocated for the GDI object. For each object type this function calls the
232 * appropriate cleanup routine.
233 *
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.
238 *
239 * \return Returns TRUE if succesful.
240 *
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.
243 */
244 BOOL STDCALL GDIOBJ_FreeObj(HGDIOBJ hObj, WORD Magic, DWORD Flag)
245 {
246 PGDIOBJHDR objectHeader;
247 PGDI_HANDLE_ENTRY handleEntry;
248 PGDIOBJ Obj;
249 BOOL bRet = TRUE;
250
251 handleEntry = GDIOBJ_iGetHandleEntryForIndex ((WORD)hObj & 0xffff);
252 DPRINT("GDIOBJ_FreeObj: hObj: %d, magic: %x, handleEntry: %x\n", (WORD)hObj & 0xffff, Magic, handleEntry );
253
254 if (handleEntry == 0 || (handleEntry->wMagic != Magic && Magic != GO_MAGIC_DONTCARE )
255 || ((handleEntry->hProcessId != PsGetCurrentProcessId()) && !(Flag & GDIOBJFLAG_IGNOREPID))){
256
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)) );
258 return FALSE;
259 }
260
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);
272 return TRUE;
273 }
274 ExReleaseFastMutex(&RefCountHandling);
275 }
276
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 );
282 break;
283 case GO_BITMAP_MAGIC:
284 bRet = Bitmap_InternalDelete( (PBITMAPOBJ) Obj );
285 break;
286 case GO_DC_MAGIC:
287 bRet = DC_InternalDeleteDC( (PDC) Obj );
288 break;
289 case GO_PEN_MAGIC:
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:
297
298 case GO_BRUSH_MAGIC:
299 case GO_FONT_MAGIC:
300 break;
301 case GO_DCE_MAGIC:
302 bRet = DCE_InternalDelete( (PDCE) Obj );
303 break;
304 }
305 handleEntry->hProcessId = 0;
306 ExFreePool (handleEntry->pObject);
307 handleEntry->pObject = 0;
308 handleEntry->wMagic = 0;
309
310 return TRUE;
311 }
312
313 /*!
314 * Return pointer to the object by handle.
315 *
316 * \param hObj Object handle
317 * \param Magic one of the magic numbers defined in \ref GDI Magic
318 * \return Pointer to the object.
319 *
320 * \note Process can only get pointer to the objects it created or global objects.
321 *
322 * \todo Don't allow to lock the objects twice! Synchronization!
323 */
324 PGDIOBJ FASTCALL GDIOBJ_LockObj( HGDIOBJ hObj, WORD Magic )
325 {
326 PGDI_HANDLE_ENTRY handleEntry = GDIOBJ_iGetHandleEntryForIndex ((WORD) hObj & 0xffff);
327 PGDIOBJHDR objectHeader;
328
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);
334 return NULL;
335 }
336
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));
342 }
343
344 ExAcquireFastMutex(&RefCountHandling);
345 objectHeader->dwCount++;
346 ExReleaseFastMutex(&RefCountHandling);
347 return (PGDIOBJ)((PCHAR)objectHeader + sizeof(GDIOBJHDR));
348 }
349
350 /*!
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!
353 *
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.
357 *
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.
359 */
360 BOOL FASTCALL GDIOBJ_LockMultipleObj( PGDIMULTILOCK pList, INT nObj )
361 {
362 INT i, j;
363 ASSERT( pList );
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;
372 break;
373 }
374 }
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 );
378 }
379 }
380 return TRUE;
381 }
382
383 /*!
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.
386
387 * \param hObj Object handle
388 * \param Magic one of the magic numbers defined in \ref GDI Magic
389 *
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.
392 *
393 * \todo Change synchronization algorithm.
394 */
395 BOOL FASTCALL GDIOBJ_UnlockObj( HGDIOBJ hObj, WORD Magic )
396 {
397 PGDI_HANDLE_ENTRY handleEntry = GDIOBJ_iGetHandleEntryForIndex ((WORD) hObj & 0xffff);
398 PGDIOBJHDR objectHeader;
399
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");
405 return FALSE;
406 }
407
408 objectHeader = (PGDIOBJHDR) handleEntry->pObject;
409 ASSERT(objectHeader);
410
411 ExAcquireFastMutex(&RefCountHandling);
412 if( ( objectHeader->dwCount & ~0x80000000 ) == 0 ){
413 ExReleaseFastMutex(&RefCountHandling);
414 DPRINT( "GDIOBJ_UnLockObj: unlock object that is not locked\n" );
415 return FALSE;
416 }
417
418 objectHeader = (PGDIOBJHDR) handleEntry->pObject;
419 ASSERT(objectHeader);
420 objectHeader->dwCount--;
421
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 );
428 }
429 ExReleaseFastMutex(&RefCountHandling);
430 return TRUE;
431 }
432
433
434 /*!
435 * Unlock multiple objects. Use this function when you need to unlock multiple objects and some of them may be
436 * duplicates.
437 *
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
440 *
441 * \note this function uses O(n^2) algoritm because we shouldn't need to call it with more than 3 or 4 objects.
442 */
443 BOOL FASTCALL GDIOBJ_UnlockMultipleObj( PGDIMULTILOCK pList, INT nObj )
444 {
445 INT i, j;
446 ASSERT( pList );
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;
454 }
455 }
456 GDIOBJ_UnlockObj( (pList+i)->hObj, (pList+i)->Magic );
457 (pList+i)->pObj = NULL;
458 }
459 }
460 return TRUE;
461 }
462
463 /*!
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.
467 *
468 * \note Only stock objects should be marked global.
469 */
470 VOID FASTCALL GDIOBJ_MarkObjectGlobal(HGDIOBJ ObjectHandle)
471 {
472 PGDI_HANDLE_ENTRY handleEntry;
473
474 if (ObjectHandle == NULL)
475 return;
476
477 handleEntry = GDIOBJ_iGetHandleEntryForIndex ((WORD)ObjectHandle & 0xffff);
478 if (handleEntry == 0)
479 return;
480
481 handleEntry->hProcessId = (HANDLE)0xFFFFFFFF;
482 }
483
484 /*!
485 * Get the type (magic value) of the object.
486 * \param ObjectHandle - handle of the object.
487 * \return GDI Magic value.
488 */
489 WORD FASTCALL GDIOBJ_GetHandleMagic (HGDIOBJ ObjectHandle)
490 {
491 PGDI_HANDLE_ENTRY handleEntry;
492
493 if (ObjectHandle == NULL)
494 return 0;
495
496 handleEntry = GDIOBJ_iGetHandleEntryForIndex ((WORD)ObjectHandle & 0xffff);
497 if (handleEntry == 0 ||
498 (handleEntry->hProcessId != (HANDLE)0xFFFFFFFF &&
499 handleEntry->hProcessId != PsGetCurrentProcessId ()))
500 return 0;
501
502 return handleEntry->wMagic;
503 }
504
505 /*!
506 * Initialization of the GDI object engine.
507 */
508 VOID FASTCALL
509 InitGdiObjectHandleTable (VOID)
510 {
511 DPRINT ("InitGdiObjectHandleTable\n");
512 ExInitializeFastMutex (&HandleTableMutex);
513 ExInitializeFastMutex (&RefCountHandling);
514
515 HandleTable = GDIOBJ_iAllocHandleTable (GDI_HANDLE_NUMBER);
516 DPRINT("HandleTable: %x\n", HandleTable );
517
518 InitEngHandleTable();
519 }
520
521 /*!
522 * Creates a bunch of stock objects: brushes, pens, fonts.
523 */
524 VOID FASTCALL CreateStockObjects(void)
525 {
526 // Create GDI Stock Objects from the logical structures we've defined
527
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]);
540
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]);
547
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]);
560
561 StockObjects[DEFAULT_PALETTE] = (HGDIOBJ*)PALETTE_Init();
562 }
563
564 /*!
565 * Return stock object.
566 * \param Object - stock object id.
567 * \return Handle to the object.
568 */
569 HGDIOBJ STDCALL W32kGetStockObject(INT Object)
570 {
571 // check when adding new objects
572 if( (Object < 0) || (Object >= NB_STOCK_OBJECTS) )
573 return NULL;
574 return StockObjects[Object];
575 }
576
577 /*!
578 * Delete GDI object
579 * \param hObject object handle
580 * \return if the function fails the returned value is NULL.
581 */
582 BOOL STDCALL W32kDeleteObject(HGDIOBJ hObject)
583 {
584 return GDIOBJ_FreeObj( hObject, GO_MAGIC_DONTCARE, GDIOBJFLAG_DEFAULT );
585 }
586
587 /*!
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.
590 */
591 BOOL STDCALL W32kCleanupForProcess( INT Process )
592 {
593 DWORD i;
594 PGDI_HANDLE_ENTRY handleEntry;
595 PGDIOBJHDR objectHeader;
596
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 );
603 }
604 }
605 return TRUE;
606 }
607
608 /*!
609 * Internal function. Dumps all the objects for the given process.
610 * \param If process == 0 dump all the objects.
611 *
612 */
613 VOID STDCALL W32kDumpGdiObjects( INT Process )
614 {
615 DWORD i;
616 PGDI_HANDLE_ENTRY handleEntry;
617 PGDIOBJHDR objectHeader;
618
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);
624 }
625 }
626
627 }
628 /* EOF */