Our current gdi handle and handle table entry code uses a bunch of
macros, masks, bitshifts and even hardcoded values, iirc.
This leads imo to errors, will make the code less portable and cannot
make use of better compiler optimizations.
So I have created a new GDI_TABLE_ENTRY struct and a new type GDIHANDLE.
Both use unions and packed structs to
directly access all fields. GDI_TABLE_ENTRY is completely compatible to
our current one, so all the code would still be valid.
+ the compiler can optimize access of single elements better (movzx,
byte ptr ...)
+ no more need for additional masks, shifts and macros
+ no more messed up code because of wrong hardcoded values
+ better readable code
+ probably easier porting to 64 bits
- must be redefined for big-endian systems
- direct access of stockbit is slightly slower, but could still be
handled by a macro
#pragma pack(push,1)
typedef struct
{
PVOID KernelData; /* Points to the kernel mode structure */
union
{
DWORD ProcessId; /* process id that created the object, 0 for
kernel objects */
struct
{
unsigned ProcessId16: 16;
unsigned Unused: 16;
};
};
union
{
ULONG Type;
struct
{
union
{
unsigned TypeLower: 16;
struct
{
union
{
unsigned HandleTypeStock: 8;
struct
{
unsigned HandleType: 7;
unsigned StockBit: 1;
};
};
unsigned ReuseCount: 8;
};
};
union
{
unsigned TypeUpper: 16;
struct
{
unsigned StorageType: 8; /* PEN uses same value as
BRUSH here, no stock bit */
unsigned Flags: 8;
};
};
};
};
PVOID UserData; /* Points to the user mode structure, usually NULL
though */
} GDI_TABLE_ENTRY, *PGDI_TABLE_ENTRY;;
typedef union
{
HGDIOBJ Handle;
struct
{
unsigned Index: 16;
union
{
unsigned Upper: 16;
struct
{
union
{
unsigned HandleTypeStock: 8;
struct
{
unsigned HandleType: 7;
unsigned StockBit: 1;
};
};
unsigned ReuseCount: 8;
};
};
};
} GDIHANDLE, *PGDIHANDLE;
#pragma pack(pop)