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.


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;
0x04 0x08
QMSG *pqmsgPrev;
0x08 0x10
MSG msg;
0x24 0x40 unaccounted 6.2 and higher  
0x24 (3.10 to 6.1);
0x40 (5.2 to 6.1);
LONG_PTR ExtraInfo;
0x28 (6.0 to 6.1);
0x48 (6.0 to 6.1);
POINT ptMouseReal;
6.0 and higher  
0x28 (3.10 to 5.2);
0x30 (6.0 to 6.1);
DWORD dwQEvent;
3.10 to early 5.2  
0x48 (5.2);
0x50 (6.0 to 6.1);
struct {
    /*  bit fields, see below  */
late 5.2 to 6.1  
DWORD dwQEvent;
6.2 and higher  
0x34 (6.1);
0x54 (6.1);
struct {
    /*  bit fields, see below  */
6.1 and higher  
0x2C (3.10 to 5.2);
0x34 (6.0);
0x38 (6.1);
0x50 (5.2);
0x58 (6.0 to 6.1);
all last member in 3.10 to 6.0
0x40 0x68 unknown qword 6.2 and higher  
0x3C (6.1);
0x60 (6.1);
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);
0x80 (6.2);
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
INT Wow64Message : 1;
6.1 and higher previously combined with dwQEvent
INT NoCoalesce : 1;
6.1 and higher previously combined with dwQEvent
INT FromTouch : 1;
6.1 and higher  
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.