QMSG

The QMSG structure (formally tagQMSG) is how WIN32K.SYS—and before it, WINSRV.DLL—dresses up a window message while it’s in a message queue. If you like, it is the internal wrapper around the documented MSG structure.

Documentation Status

The QMSG is not documented. Though symbol files for WIN32K.SYS in Windows 8 and higher name the QMSG in the C++ decorations of internal routines, type information for the structure is present only in symbol files for Windows 7—not before and not since.

Layout

The symbol files for Windows 7 are anyway incorrect. Windows 7 appended a MSGPPINFO which the symbol files have as four bytes even though the matching executable plainly understands the structure to be eight bytes. The size of the QMSG as given in the symbol file for the 32-bit WIN32K is thus wrong by four bytes. For the 64-bit build, the extra four bytes are covered by the QMSG structure’s eight-byte alignment. Over the whole history, the following changes of size are known:

Version Size (x86) Size (x64) Remarks
3.10 to 5.2 0x30 0x58  
6.0 0x38 0x60  
6.1 0x44 0x68 0x40 (x86) according to symbol files
6.2 0x60 0x88  
6.3 0x60 0x90  
10.0 0x68 0x90  

For versions other than 6.1, these sizes, and the offsets that the next table shows for members, are obtained by inspecting the executable for correspondences with the executable from version 6.1 and assuming as much continuity as possible for the names or types. Microsoft’s names and types for members that have been added since version 6.1 may never be known.

Offset (x86) Offset (x64) Definition Versions Remarks
0x00 0x00
QMSG *pqmsgNext;
all  
0x04 0x08
QMSG *pqmsgPrev;
all  
0x08 0x10
MSG msg;
all  
0x24 0x40 unaccounted 6.2 and higher  
0x24 (3.10 to 6.1);
0x28
0x40 (5.2 to 6.1);
0x48
LONG_PTR ExtraInfo;
all  
0x28 (6.0 to 6.1);
0x2C
0x48 (6.0 to 6.1);
0x50
POINT ptMouseReal;
6.0 and higher  
0x28 (3.10 to 5.2);
0x30 (6.0 to 6.1);
0x34
 
DWORD dwQEvent;
3.10 to early 5.2  
0x48 (5.2);
0x50 (6.0 to 6.1);
0x58
struct {
    /*  bit fields, see below  */
};
late 5.2 to 6.1  
DWORD dwQEvent;
6.2 and higher  
0x34 (6.1);
0x38
0x54 (6.1);
0x5C
struct {
    /*  bit fields, see below  */
};
6.1 and higher  
0x2C (3.10 to 5.2);
0x34 (6.0);
0x38 (6.1);
0x3C
0x50 (5.2);
0x58 (6.0 to 6.1);
0x60
THREADINFO *pti;
all last member in 3.10 to 6.0
0x40 0x68 unknown qword 6.2 and higher  
0x3C (6.1);
0x48
0x60 (6.1);
0x70
MSGPPINFO MsgPPInfo;
6.1 and higher last member in 6.1
0x50 0x78 unknown qword 6.2 and higher  
0x58 0x80 unknown pointer 6.3 and higher  
00x58 (6.2);
0x5C
0x80 (6.2);
0x88
unknown dword 6.2 and higher last member in 6.2 to 10.0

Description of the two sets of bit flags is a little complicated by their not being in union with an integral member for accessing them all together. The chronologically first flags were squeezed in as high bits of what had been the dwQEvent member as a DWORD—and later is because these high bits soon became the low bits of a new set of purposely designed bit fields.

Mask Definition Versions Remarks
0x7FFFFFFF (late 5.2);
0x3FFFFFFF (6.0 to 6.1)
DWORD dwQEvent : 31;
late 5.2  
DWORD dwQEvent : 30;
6.0 to 6.1  
0x80000000 (late 5.2);
0x40000000 (6.0)
DWORD Wow64Message : 1;
late 5.2 to 6.1 next as 0x00000001 bit in second flags
0x80000000 (6.0)
DWORD NoCoalesce : 1;
6.0 only next as 0x00000002 bit in second flags
 
DWORD Padding : 2;
6.1 only  

For the second set of flags, the following are known to be defined:

Mask Definition Versions Remarks
0x00000001
INT Wow64Message : 1;
6.1 and higher previously combined with dwQEvent
0x00000002
INT NoCoalesce : 1;
6.1 and higher previously combined with dwQEvent
0x00000004
INT FromTouch : 1;
6.1 and higher  
0x00000008
INT FromPen : 1;
6.1 and higher  
  unaccounted 6.2 and higher  

More have been defined since version 6.1, inevitably, but Microsoft’s names are not known.