Usermode GDI Objects
Usermode objects are the objects that can be accessed via handles from usermode. The pool tags either begin with Gh or Gla. If the tag begins with Gla it means the objects are allocated from a paged lookaside list, if the tag is Gh they are allocated from paged pool. The object type is stored in bits 17-24 of the handle and in bits 0-7 of the type filed in the handle table entry. Bits 17-24 of the type field are the same in most cases. They are the type masked with 0x1f or 11111 binary. A pen for example has a value of 0x30 in bits 0-7 and a value of 0x10 in bits 17-24. 0x10 is a brush and that's the structure it is stored in. So bits 17-24 describe the basic type. The following list shows all basic types as described in Feng Yuan's book. If there's a pool tag, I have found them in win xp. DX objects are handled differently on xp.
All GDI objects from the handle table have a header: BASEOBJECT
|Type id||Type||kmode struct||umode struct||pool tag|
|0x06||CLIENTOBJ (METAFILE, ENHMETAFILE, METADC)||?||?||'Gh06'|
|0x10||BRUSH (PEN, EXTPEN)||BRUSH||BRUSHATTR||'Gla@'|
|0x12||unused (move to dxg.sys internal gdi table, it is DirectDrawObject handle)||-||-|
[XP] Deleted Objects have a value of 0 in the base type field. Windows keeps track of deleted objects with a singly linked list inside the gdi handle table. The kernel mode pointer is replaced by an index to the next deleted object in the handle table. The last (in terms of time) deleted object has a kernel mode pointer of 0. This entry must not always be the deleted object with the hightest index. So windows must somehow store the index of the first deleted object and also of the first free index. The usermode pointer and the ProcessID field are 0, the rest of the type field is still the same as before the object got deleted. See 2)
Usermode GDI objects are thread safe. GDI takes care for the synchroniastion. In kernel mode there are 2 kind of locks:
- Exclusive locks - These block all other threads from accessing the object, making them wait until the object is free again. Exclusive locks must not be held for a longer time especially not after returning from a Systemcall or during user mode callbacks. Locking must be done in a special order to prevent deadlocks.
- Shared locks - These are only references to the object and prevent the object from being deleted. They do not synchronize writes to the object (NOTE: writes to a SURFACE's bits are not to be considered as writes to the SURFACE object) so these locks can only be used for objects that are immutable (once created never have their data changed) and can be held for a longer time, even after returning to user mode. Immutable objects are: pens, brushes, surfaces, lfonts, ...?
CHECKME: usermode synchronisation?
Kernel Mode GDI Objects
Kernel mode objects are used in kernel mode only and can be used by display/printer drivers. They are accessed via pointers instead of handles. They normally have a documented structure, which has only the public members. The real structure behind the objects is mostly undocumented. The real structures often have names like the documented structure with a preceeding E, like EPALOBJ
- BRUSHOBJ (EBRUSHOBJ)
- FONTOBJ (RFONT 1))
- PALOBJ (EPALOBJ, 1), 3))
- PATHOBJ (EPATHOBJ, 4))
- PFE, 'Gpfe'
- PFF, 'Gpff'
- STROBJ (ESTROBJ)
- SURFOBJ (SURFACE, 1))
- XFORMOBJ (EXFORMOBJ)
- XLATEOBJ (EXLATEOBJ)