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)