Geoff Chappell, Software Analyst
The DRIVER_EXTENSION structure is an adjunct to the well-known (though partially opaque) DRIVER_OBJECT. It was added when introduction of the PnP Manager for Windows NT 4.0 needed that drivers implement another calling point through which to learn of device addition. The address to call might be set into the DRIVER_OBJECT except for compatibility constraints. Pre-existing drivers depended on at least some members, which therefore could not shift. Members could not be appended without risking a future problem for the MajorFunction array were new types of I/O request ever to be defined. The solution was to replace the Count member, which no drivers should have been accessing, by a pointer to an extension. Thereafter, the Count and anything new that is ever wanted for the DRIVER_OBJECT go to the extension.
Because writers of device drivers that actually do drive a physical device, here meaning one that’s known to the PnP Manager, need to know of the DRIVER_EXTENSION so that they can set the AddDevice member, the DRIVER_EXTENSION has long been documented—but only indirectly and only to the bare minimum for this one need. Since the structure itself is not even mentioned in the documentation, saying it’s documented indirectly is generous. It is, however, literal: what programmers are told is that they set their AddDevice routine not directly in their driver object but indirectly through its DriverExtension member. It wasn’t until the DDK for Windows XP that they were told in the documentatin that the DriverExtension is a PDRIVER_EXTENSION and that AddDevice is “the only accessible member of the driver extension”.
A C-language definition is in the NTDDK.H from the Device Driver Kit (DDK) for Windows NT 4.0. It moved to WDM.H in the DDK for Windows 2000. No definition in the NTDDK.H or WDM.H from any DDK or in the WDM.H or NTOSP.H from any Windows Driver Kit (WDK) has yet extended beyond the ServiceKeyName member. Type information in public symbol files, however, has always told of more.
The DRIVER_EXTENSION has varied from version to version only by appending new members. The following table summarises the growing size:
Version | Size (x86) | Size (x64) |
---|---|---|
4.0 | 0x14 | |
5.0 | 0x18 | |
5.1 to 6.1 | 0x1C | 0x38 |
6.2 | 0x24 | 0x48 |
6.3 to 2004 | 0x28 | 0x50 |
These sizes, and the offsets, types and names in the tables that follow, are from Microsoft’s symbol files for the kernel starting with Windows 2000 SP3 (except as noted after the table). Before then, offsets and names are in tables in the KDEX2X86 debugger extension to support its !strct command.
Offset (x86) | Offset (x64) | Definition | Versions |
---|---|---|---|
0x00 | 0x00 |
DRIVER_OBJECT *DriverObject; |
4.0 and higher |
0x04 | 0x08 |
PDRIVER_ADD_DEVICE AddDevice; |
4.0 and higher |
0x08 | 0x10 |
ULONG Count; |
4.0 and higher |
0x0C | 0x18 |
UNICODE_STRING ServiceKeyName; |
4.0 and higher |
0x14 | 0x28 |
IO_CLIENT_EXTENSION *ClientDriverExtension; |
5.0 and higher |
0x18 | 0x30 |
FS_FILTER_CALLBACKS *FsFilterCallbacks; |
5.1 and higher |
0x1C | 0x38 |
PVOID KseCallbacks; |
6.2 and higher |
0x20 | 0x40 |
PVOID DvCallbacks; |
6.2 and higher |
0x24 | 0x48 |
PVOID VerifierContext; |
6.3 and higher |
For no reason that is yet understood, the public symbol file for the 64-bit kernel in the 2004 edition of Windows 10 would have it that the structure extends no further than ServiceKeyName. That this is deliberate, to make the type information consistent with the definition in WDM.H, seems unlikely. The type information in just this one PDB is here taken as aberrant. The corresponding symbol file for the 32-bit kernel is not affected, nor is the code in the 64-bit kernel, which continues to allow 0x50 bytes for the extension.