2 * GDIOBJ.C - GDI object manipulation routines
4 * $Id: gdiobj.c,v 1.14 2002/07/22 07:55:48 ei Exp $
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 #define GDI_HANDLE_NUMBER 0x4000
112 static PGDI_HANDLE_TABLE
113 GDIOBJ_iAllocHandleTable (WORD Size
)
115 PGDI_HANDLE_TABLE handleTable
;
117 ExAcquireFastMutexUnsafe (&HandleTableMutex
);
118 handleTable
= ExAllocatePool(PagedPool
,
119 sizeof (GDI_HANDLE_TABLE
) +
120 sizeof (GDI_HANDLE_ENTRY
) * Size
);
121 ASSERT( handleTable
);
124 sizeof (GDI_HANDLE_TABLE
) + sizeof (GDI_HANDLE_ENTRY
) * Size
);
125 handleTable
->wTableSize
= Size
;
126 ExReleaseFastMutexUnsafe (&HandleTableMutex
);
131 static PGDI_HANDLE_ENTRY
132 GDIOBJ_iGetHandleEntryForIndex (WORD TableIndex
)
134 //DPRINT("GDIOBJ_iGetHandleEntryForIndex: TableIndex: %d,\n handle: %x, ptr: %x\n", TableIndex, HandleTable->Handles [TableIndex], &(HandleTable->Handles [TableIndex]) );
135 //DPRINT("GIG: HandleTable: %x, Handles: %x, \n TableIndex: %x, pt: %x\n", HandleTable, HandleTable->Handles, TableIndex, ((PGDI_HANDLE_ENTRY)HandleTable->Handles+TableIndex));
136 //DPRINT("GIG: Hndl: %x, mag: %x\n", ((PGDI_HANDLE_ENTRY)HandleTable->Handles+TableIndex), ((PGDI_HANDLE_ENTRY)HandleTable->Handles+TableIndex)->wMagic);
137 return ((PGDI_HANDLE_ENTRY
)HandleTable
->Handles
+TableIndex
);
141 GDIOBJ_iGetNextOpenHandleIndex (void)
145 ExAcquireFastMutexUnsafe (&HandleTableMutex
);
146 for (tableIndex
= 1; tableIndex
< HandleTable
->wTableSize
; tableIndex
++)
148 if (HandleTable
->Handles
[tableIndex
].wMagic
== 0)
150 HandleTable
->Handles
[tableIndex
].wMagic
= GO_MAGIC_DONTCARE
;
154 ExReleaseFastMutexUnsafe (&HandleTableMutex
);
156 return (tableIndex
< HandleTable
->wTableSize
) ? tableIndex
: 0;
159 /*-----------------7/12/2002 11:38AM----------------
160 * Allocate memory for GDI object and return handle to it
161 * Use GDIOBJ_Lock to obtain pointer to the new object.
162 * --------------------------------------------------*/
163 HGDIOBJ
GDIOBJ_AllocObj(WORD Size
, WORD Magic
)
165 PGDIOBJHDR newObject
;
166 PGDI_HANDLE_ENTRY handleEntry
;
168 DPRINT("GDIOBJ_AllocObj: size: %d, magic: %x\n", Size
, Magic
);
169 newObject
= ExAllocatePool (PagedPool
, Size
+ sizeof (GDIOBJHDR
));
170 if (newObject
== NULL
)
174 RtlZeroMemory (newObject
, Size
+ sizeof (GDIOBJHDR
));
176 newObject
->wTableIndex
= GDIOBJ_iGetNextOpenHandleIndex ();
177 newObject
->dwCount
= 0;
178 handleEntry
= GDIOBJ_iGetHandleEntryForIndex (newObject
->wTableIndex
);
179 handleEntry
->wMagic
= Magic
;
180 handleEntry
->hProcessId
= PsGetCurrentProcessId ();
181 handleEntry
->pObject
= newObject
;
182 DPRINT("GDIOBJ_AllocObj: object handle %d\n", newObject
->wTableIndex
);
183 return (HGDIOBJ
) newObject
->wTableIndex
;
186 BOOL
GDIOBJ_FreeObj(HGDIOBJ hObj
, WORD Magic
)
188 PGDIOBJHDR objectHeader
;
189 PGDI_HANDLE_ENTRY handleEntry
;
193 handleEntry
= GDIOBJ_iGetHandleEntryForIndex ((WORD
)hObj
& 0xffff);
194 DPRINT("GDIOBJ_FreeObj: hObj: %d, magic: %x, handleEntry: %x\n", hObj
, Magic
, handleEntry
);
195 if (handleEntry
== 0 || (handleEntry
->wMagic
!= Magic
&& handleEntry
->wMagic
!= GO_MAGIC_DONTCARE
)
196 || handleEntry
->hProcessId
!= PsGetCurrentProcessId ())
199 objectHeader
= (PGDIOBJHDR
) handleEntry
->pObject
;
200 ASSERT(objectHeader
);
202 // check that the reference count is zero. if not then set flag
203 // and delete object when releaseobj is called
204 ExAcquireFastMutex(&RefCountHandling
);
205 if( ( objectHeader
->dwCount
& ~0x80000000 ) > 0 ){
206 objectHeader
->dwCount
|= 0x80000000;
207 DPRINT("GDIOBJ_FreeObj: delayed object deletion");
208 ExReleaseFastMutex(&RefCountHandling
);
211 ExReleaseFastMutex(&RefCountHandling
);
213 //allow object to delete internal data
214 Obj
= (PGDIOBJ
)((PCHAR
)handleEntry
->pObject
+ sizeof(GDIOBJHDR
));
215 switch( handleEntry
->wMagic
){
216 case GO_REGION_MAGIC
:
217 bRet
= RGNDATA_InternalDelete( (PROSRGNDATA
) Obj
);
220 case GO_PALETTE_MAGIC
:
221 case GO_BITMAP_MAGIC
:
222 bRet
= Bitmap_InternalDelete( (PBITMAPOBJ
) Obj
);
225 bRet
= DC_InternalDeleteDC( (PDC
) Obj
);
227 case GO_DISABLED_DC_MAGIC
:
228 case GO_META_DC_MAGIC
:
229 case GO_METAFILE_MAGIC
:
230 case GO_METAFILE_DC_MAGIC
:
231 case GO_ENHMETAFILE_MAGIC
:
232 case GO_ENHMETAFILE_DC_MAGIC
:
238 handleEntry
->hProcessId
= 0;
239 ExFreePool (handleEntry
->pObject
);
240 handleEntry
->pObject
= 0;
241 // (RJJ) set wMagic last to avoid race condition
242 handleEntry
->wMagic
= 0;
248 PGDIOBJ
GDIOBJ_LockObj( HGDIOBJ hObj
, WORD Magic
)
250 PGDI_HANDLE_ENTRY handleEntry
= GDIOBJ_iGetHandleEntryForIndex ((WORD
) hObj
& 0xffff);
251 PGDIOBJHDR objectHeader
;
253 DPRINT("GDIOBJ_LockObj: hObj: %d, magic: %x, \n handleEntry: %x, mag %x\n", hObj
, Magic
, handleEntry
, handleEntry
->wMagic
);
254 if (handleEntry
== 0 || (handleEntry
->wMagic
!= Magic
&& handleEntry
->wMagic
!= GO_MAGIC_DONTCARE
)
255 || handleEntry
->hProcessId
!= PsGetCurrentProcessId () )
258 objectHeader
= (PGDIOBJHDR
) handleEntry
->pObject
;
259 ASSERT(objectHeader
);
261 ExAcquireFastMutex(&RefCountHandling
);
262 objectHeader
->dwCount
++;
263 ExReleaseFastMutex(&RefCountHandling
);
265 DPRINT("GDIOBJ_LockObj: PGDIOBJ %x\n", ((PCHAR
)objectHeader
+ sizeof(GDIOBJHDR
)) );
266 return (PGDIOBJ
)((PCHAR
)objectHeader
+ sizeof(GDIOBJHDR
));
269 BOOL
GDIOBJ_UnlockObj( HGDIOBJ hObj
, WORD Magic
)
271 PGDI_HANDLE_ENTRY handleEntry
= GDIOBJ_iGetHandleEntryForIndex ((WORD
) hObj
& 0xffff);
272 PGDIOBJHDR objectHeader
;
274 DPRINT("GDIOBJ_UnlockObj: hObj: %d, magic: %x, \n handleEntry: %x\n", hObj
, Magic
, handleEntry
);
275 if (handleEntry
== 0 || (handleEntry
->wMagic
!= Magic
&& handleEntry
->wMagic
!= GO_MAGIC_DONTCARE
)
276 || handleEntry
->hProcessId
!= PsGetCurrentProcessId ())
279 objectHeader
= (PGDIOBJHDR
) handleEntry
->pObject
;
280 ASSERT(objectHeader
);
282 ExAcquireFastMutex(&RefCountHandling
);
283 if( ( objectHeader
->dwCount
& ~0x80000000 ) == 0 ){
284 ExReleaseFastMutex(&RefCountHandling
);
285 DPRINT( "GDIOBJ_UnLockObj: unlock object that is not locked\n" );
289 objectHeader
= (PGDIOBJHDR
) handleEntry
->pObject
;
290 ASSERT(objectHeader
);
291 objectHeader
->dwCount
--;
293 if( objectHeader
->dwCount
== 0x80000000 ){
294 //delayed object release
295 objectHeader
->dwCount
= 0;
296 ExReleaseFastMutex(&RefCountHandling
);
297 DPRINT("GDIOBJ_UnlockObj: delayed delete\n");
298 return GDIOBJ_FreeObj( hObj
, Magic
);
300 ExReleaseFastMutex(&RefCountHandling
);
305 PGDIOBJ GDIOBJ_AllocObject(WORD Size, WORD Magic)
307 PGDIOBJHDR newObject;
308 PGDI_HANDLE_ENTRY handleEntry;
310 newObject = ExAllocatePool (PagedPool, Size + sizeof (GDIOBJHDR));
311 if (newObject == NULL)
315 RtlZeroMemory (newObject, Size + sizeof (GDIOBJHDR));
317 newObject->wTableIndex = GDIOBJ_iGetNextOpenHandleIndex ();
318 handleEntry = GDIOBJ_iGetHandleEntryForIndex (newObject->wTableIndex);
319 handleEntry->wMagic = Magic;
320 handleEntry->hProcessId = PsGetCurrentProcessId ();
321 handleEntry->pObject = newObject;
323 return (PGDIOBJ)(((PCHAR) newObject) + sizeof (GDIOBJHDR));
326 BOOL GDIOBJ_FreeObject (PGDIOBJ Obj, WORD Magic)
328 PGDIOBJHDR objectHeader;
329 PGDI_HANDLE_ENTRY handleEntry;
331 objectHeader = (PGDIOBJHDR)(((PCHAR)Obj) - sizeof (GDIOBJHDR));
332 handleEntry = GDIOBJ_iGetHandleEntryForIndex (objectHeader->wTableIndex);
333 if (handleEntry == 0 || handleEntry->wMagic != Magic)
335 handleEntry->hProcessId = 0;
336 handleEntry->pObject = 0;
337 // (RJJ) set wMagic last to avoid race condition
338 handleEntry->wMagic = 0;
339 ExFreePool (objectHeader);
344 HGDIOBJ GDIOBJ_PtrToHandle (PGDIOBJ Obj, WORD Magic)
346 PGDIOBJHDR objectHeader;
347 PGDI_HANDLE_ENTRY handleEntry;
351 objectHeader = (PGDIOBJHDR) (((PCHAR)Obj) - sizeof (GDIOBJHDR));
352 handleEntry = GDIOBJ_iGetHandleEntryForIndex (objectHeader->wTableIndex);
353 if (handleEntry == 0 ||
354 handleEntry->wMagic != Magic ||
355 handleEntry->hProcessId != PsGetCurrentProcessId () )
358 return (HGDIOBJ) objectHeader->wTableIndex;
361 PGDIOBJ GDIOBJ_HandleToPtr (HGDIOBJ ObjectHandle, WORD Magic)
363 PGDI_HANDLE_ENTRY handleEntry;
365 if (ObjectHandle == NULL)
368 handleEntry = GDIOBJ_iGetHandleEntryForIndex ((WORD)ObjectHandle & 0xffff);
369 if (handleEntry == 0 ||
370 (Magic != GO_MAGIC_DONTCARE && handleEntry->wMagic != Magic) ||
371 handleEntry->hProcessId != PsGetCurrentProcessId () )
374 return (PGDIOBJ) (((PCHAR)handleEntry->pObject) + sizeof (GDIOBJHDR));
378 WORD
GDIOBJ_GetHandleMagic (HGDIOBJ ObjectHandle
)
380 PGDI_HANDLE_ENTRY handleEntry
;
382 if (ObjectHandle
== NULL
)
385 handleEntry
= GDIOBJ_iGetHandleEntryForIndex ((WORD
)ObjectHandle
& 0xffff);
386 if (handleEntry
== 0 ||
387 handleEntry
->hProcessId
!= PsGetCurrentProcessId ())
390 return handleEntry
->wMagic
;
394 InitGdiObjectHandleTable (void)
396 DPRINT ("InitGdiObjectHandleTable\n");
397 ExInitializeFastMutex (&HandleTableMutex
);
398 ExInitializeFastMutex (&RefCountHandling
);
399 //per http://www.wd-mag.com/articles/1999/9902/9902b/9902b.htm?topic=articles
400 //gdi handle table can hold 0x4000 handles
401 HandleTable
= GDIOBJ_iAllocHandleTable (GDI_HANDLE_NUMBER
);
402 DPRINT("HandleTable: %x\n", HandleTable
);
405 VOID
CreateStockObjects(void)
407 // Create GDI Stock Objects from the logical structures we've defined
409 StockObjects
[WHITE_BRUSH
] = W32kCreateBrushIndirect(&WhiteBrush
);
410 StockObjects
[LTGRAY_BRUSH
] = W32kCreateBrushIndirect(&LtGrayBrush
);
411 StockObjects
[GRAY_BRUSH
] = W32kCreateBrushIndirect(&GrayBrush
);
412 StockObjects
[DKGRAY_BRUSH
] = W32kCreateBrushIndirect(&DkGrayBrush
);
413 StockObjects
[BLACK_BRUSH
] = W32kCreateBrushIndirect(&BlackBrush
);
414 StockObjects
[NULL_BRUSH
] = W32kCreateBrushIndirect(&NullBrush
);
416 StockObjects
[WHITE_PEN
] = W32kCreatePenIndirect(&WhitePen
);
417 StockObjects
[BLACK_PEN
] = W32kCreatePenIndirect(&BlackPen
);
418 StockObjects
[NULL_PEN
] = W32kCreatePenIndirect(&NullPen
);
420 StockObjects
[OEM_FIXED_FONT
] = W32kCreateFontIndirect(&OEMFixedFont
);
421 StockObjects
[ANSI_FIXED_FONT
] = W32kCreateFontIndirect(&AnsiFixedFont
);
422 StockObjects
[SYSTEM_FONT
] = W32kCreateFontIndirect(&SystemFont
);
423 StockObjects
[DEVICE_DEFAULT_FONT
] = W32kCreateFontIndirect(&DeviceDefaultFont
);
424 StockObjects
[SYSTEM_FIXED_FONT
] = W32kCreateFontIndirect(&SystemFixedFont
);
425 StockObjects
[DEFAULT_GUI_FONT
] = W32kCreateFontIndirect(&DefaultGuiFont
);
427 StockObjects
[DEFAULT_PALETTE
] = (HGDIOBJ
*)PALETTE_Init();
430 HGDIOBJ STDCALL
W32kGetStockObject(INT Object
)
434 /* if ((Object < 0) || (Object >= NB_STOCK_OBJECTS)) return 0;
435 if (!StockObjects[Object]) return 0;
436 ret = FIRST_STOCK_HANDLE + Object;
440 return StockObjects
[Object
]; // FIXME........
443 BOOL STDCALL
W32kDeleteObject(HGDIOBJ hObject
)
445 return GDIOBJ_FreeObj( hObject
, GO_MAGIC_DONTCARE
);
448 // dump all the objects for process. if process == 0 dump all the objects
449 VOID STDCALL
W32kDumpGdiObjects( INT Process
)
452 PGDI_HANDLE_ENTRY handleEntry
;
453 PGDIOBJHDR objectHeader
;
455 for( i
=1; i
< GDI_HANDLE_NUMBER
; i
++ ){
456 handleEntry
= GDIOBJ_iGetHandleEntryForIndex ((WORD
) i
& 0xffff);
457 if( handleEntry
&& handleEntry
->wMagic
!= 0 ){
458 objectHeader
= (PGDIOBJHDR
) handleEntry
->pObject
;
459 DPRINT("\nHandle: %d, magic: %x \n process: %d, locks: %d", i
, handleEntry
->wMagic
, handleEntry
->hProcessId
, objectHeader
->dwCount
);