What is ContextSizeOverride and how do I use it?
One of the lesser used fields in
WDF_OBJECT_ATTRIBUTES
is
ContextSizeOverride. In a typical KMDF driver,
this field is never used because the
ContextTypeInfo field of the structure specifies
the size of the context to be associated with the object. The
ContextTypeInfo field is set for you when you call either
WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE or
WDF_OBJECT_ATTRIBUTES_SET_CONTEXT_TYPE. The size
specified in
ContextTypeInfo is set to
sizeof( <CONTEXT STRUCT> ).
But when is
sizeof( <CONTEXT STRUCT> ) the wrong
size? Well, if you have a variable length structure, such as this one:
typedef struct _OBJECT_CONTEXT {
[...other fields...]
ULONG BufferSize;
UCHAR Buffer[1];
} OBJECT_CONTEXT, *POBJECT_CONTEXT;
and you want to have OBJECT_CONTEXT be large enough to reference
BufferSize number of bytes in one continguous
allocation. This is the scenario in which you would use
ContextSizeOverride to allocate a context
whose size is not constant. To use the field, you would write something like this:
WDF_OBJECT_ATTRIBUTES woa;
//
// You still need to initialize context type to get a context
//
WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&woa, DEVICE_CONTEXT);
//
// 1 Compute the size of the fixed part of our context. By using FIELD_OFFSET,
// we make sure that we are taking into account any padding the compiler adds
// between BufferSize and Buffer.
//
// 2 Compute the variable size of our context
//
woa.ContextSizeOverride = FIELD_OFFSET(OBJECT_CONTEXT, Buffer) + // 1
<compute the variable size>; // 2
Now some might question the merit of such a design pattern in the first place,
but when we created the context type infrastructure in KMDF we didn't want to
create a restriction that would hinder adoption and variable sized data structures
are somewhat common in C already. The nice thing about this feature is that if you
don't have to use it, you never have to bother with this field, it is truly
an opt-in feature that only adds complexity when it is used.