ETW_REG_ENTRY

The ETW_REG_ENTRY structure (formally _ETW_REG_ENTRY) is the kernel’s representation of an event registration object. This can exist as a formal object, with handles and access control, or not. The typical case in which an instance is created as a formal object is when an event provider is registered from user mode. The object type is named EtwRegistration. Note that the kernel has no exported variable for this object type, presumably because only the kernel is ever involved in interpreting a handle that refers to such an object.

Documentation Status

The ETW_REG_ENTRY structure is not documented.

Layout

For a non-trivial structure that is plainly very much internal to the kernel, the ETW_REG_ENTRY has been relatively stable. There has been growth, inevitably, but the only rearrangement was that version 6.2 compacts a few members and moves them towards the end.

Version Size (x86) Size (x64)
6.0 to 6.1 0x2C 0x50
6.2 to 6.3 0x28 0x50
10.0 0x3C 0x70

The preceding sizes, and the offsets, types and names in the table below are from Microsoft’s symbol files for the kernel starting with Windows Vista.

Offset (x86) Offset (x64) Definition Versions Remarks
0x00 0x00
LIST_ENTRY RegList;
6.0 and higher  
0x08 0x10
LIST_ENTRY GroupRegList;
10.0 and higher  
0x08 (6.0 to 6.3);
0x10
0x10 (6.0 to 6.3);
0x20
ETW_GUID_ENTRY *GuidEntry;
6.0 and higher  
0x14 0x28
ETW_GUID_ENTRY *GroupEntry;
10.0 and higher  
0x0C (6.0 to 6.1) 0x18 (6.0 to 6.1)
USHORT Index;
6.0 to 6.1 next at 0x24 and 0x48
0x0E (6.0 to 6.1) 0x1A (6.0 to 6.1)
USHORT Flags;
6.0 to 6.1 next as UCHAR at 0x26 and 0x4A
0x10 (6.0 to 6.1) 0x1C (6.0 to 6.1)
UCHAR EnableMask;
6.0 to 6.1 next at 0x27 and 0x4B
0x14 (6.0 to 6.1);
0x0C (6.2 to 6.3);
0x18
0x20 (6.0 to 6.1);
0x18 (6.2 to 6.3);
0x30
union {
    /*  changing members, see below  */
};
6.0 and higher  
0x24 (6.0 to 6.1);
0x1C (6.2 to 6.3);
0x28
0x40 (6.0 to 6.1);
0x38 (6.2 to 6.3);
0x50
union {
    EPROCESS *Process;
    struct {
        PVOID Callback;
        PVOID CallbackContext;
    };
};
6.0 to 6.1 last member in 6.0 to 6.1
union {
    EPROCESS *Process;
    struct {
        PVOID CallbackContext;
        PVOID Callback;
    };
};
6.2 and higher  
0x24 (6.2 to 6.3);
0x30
0x48 (6.2 to 6.3);
0x60
USHORT Index;
6.2 and higher previously at 0x0C and 0x18
0x26 (6.2 to 6.3);
0x32
0x4A (6.2 to 6.3);
0x62
union {
    UCHAR Flags;
    struct {
        /*  bit fields, follow link  */
    };
};
6.2 to 1511 previously USHORT at 0x0E and 01A
union {
    USHORT Flags;
    struct {
        /*  bit fields, follow link  */
    };
};
1607 and higher  
0x27 (6.2 to 6.3);
0x33 (10.0 to 1511);
0x34
0x4B (6.2 to 6.3);
0x63 (10.0 to 1511);
0x64
UCHAR EnableMask;
6.2 and higher previously at 0x10 and 0x1C;
last member in 6.2 to 6.3
0x34 (10.0 to 1511);
0x35
0x64 (10.0 to 1511);
0x65
UCHAR GroupEnableMask;
10.0 and higher  
0x35 (10.0 to 1511);
0x36 (1607 to 1703)
0x65 (10.0 to 1511);
0x66 (1607 to 1703)
BOOLEAN UseDescriptorType;
10.0 to 1703 next in Flags
0x38 0x68
ETW_PROVIDER_TRAITS *Traits;
10.0 and higher last member in 10.0 and higher

Any number of registrations can be opened to any one event provider. The ETW_REG_ENTRY structures for the registrations are linked through the RegList member to the RegListHead in the ETW_GUID_ENTRY that represents the provider (and whose address is the GuidEntry). There are also ETW_REG_ENTRY structures that exist only to support a notification mechanism. These reply objects are not associated with any provider. They have their own list, again linking through RegList, but with a head that is an internal variable in the kernel’s data.

Each registration allows that its holder can write events through the provider. On the other side, the provider can be accessed by as many as eight loggers, known more formally as event tracing sessions. The eight bits of the EnableMask track which of the possible loggers are enabled.

Reply Queue and Slot

Space for four pointers in the middle of the structure is used very differently in the different types of object.

Offset (x86) Offset (x64) Definition Versions
0x14 (6.1) 0x20 (6.1)
ULONG SessionId;
6.1 only
0x14 (6.0 to 6.1);
0x0C (6.2 to 6.3);
0x18
0x20 (6.0 to 6.1);
0x18 (6.2 to 6.3);
0x30
ETW_REPLY_QUEUE *ReplyQueue;
6.0 and higher
0x14 (6.0 to 6.1);
0x0C (6.2 to 6.3);
0x18
0x20 (6.0 to 6.1);
0x18 (6.2 to 6.3);
0x30
ETW_REG_ENTRY *ReplySlot [4];
6.0 to 6.1
ETW_QUEUE_ENTRY *ReplySlot [4];
6.2 and higher
0x0C (6.2 to 6.3);
0x18
0x18 (6.2 to 6.3);
0x30
struct {
    PVOID Caller;
    ULONG SessionId;
};
6.2 and higher

The ReplyQueue is meaningful in a registration object that has DbgReplyRegistration set among the Flags to denote that it exists to support the retrieval of replies to a notification.

A registration object for which DbgUserRegistration is set can be sent notifications which may request replies. The ReplySlot array is how the replies are kept until their retrieval.

The SessionId and later the Caller are meaningful only for kernel-mode registrations, i.e., when DbgKernelRegistration is set. The Caller is in fact older but was kept separately from the ETW_REG_ENTRY as a member of the ETW_PROVIDER_TABLE_ENTRY.