Geoff Chappell - Software Analyst
The IOP_IRP_EXTENSION structure supports IRP extensions, which are new functionality for Windows 8. All known instances of the structure are pointed to from an IRP via the latter’s Tail.Overlay.IrpExtension member. Since the most readily available definitions of the IRP, e.g., in WDM.H, do not show anything named IrpExtension, it may be as well to note that this pointer is at offsets 0x68 and 0xC8 in the x86 and x64 builds, respectively.
All Windows versions that support IRP extensions allow that the IOP_IRP_EXTENSION may be in the same memory block as the IRP, after the I/O stack locations, or that it may be a separate allocation (from non-paged no-execute pool). Given that the kernel has highly efficient allocation of I/O Request Packets from per-processor lookaside lists, fitting the IRP extension into the packet in one memory block is clearly desirable.
As an internal structure, the IOP_IRP_EXTENSION must be expected to vary between versions, and it already has. The changing size gives a rough guide to the variability:
Version | Size (x86) | Size (x64) |
---|---|---|
6.2 | 0x20 | 0x20 |
6.3 | 0x24 | 0x28 |
10.0 to 1511 | 0x28 | 0x30 |
1607 | 0x2C | 0x38 |
1703 and higher | 0x30 | 0x38 |
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 8.1.
Offset (x86) | Offset (x64) | Definition | Versions |
---|---|---|---|
0x00 | 0x00 |
union { USHORT ExtensionFlags; struct { /* bit fields, see below */ }; }; |
6.2 and higher |
0x02 | 0x02 |
USHORT TypesAllocated; |
6.2 and higher |
0x04 | 0x04 |
UCHAR GenericExtension [4]; |
6.3 and higher |
0x08 | 0x08 |
PVOID VerifierContext; |
6.3 and higher |
0x0C | 0x10 |
ULONG_PTR DiskIoAttributionHandle; |
1607 and higher |
0x04 (6.2); 0x0C (6.3 to 1511); 0x10 |
0x04 (6.2); 0x10 (6.3 to 1511); 0x18 |
GUID ActivityId; |
6.2 and higher |
0x18 (6.2); 0x1C (6.3 to 1511); 0x20 |
0x18 (6.2); 0x20 (6.3 to 1511); 0x28 |
LARGE_INTEGER Timestamp; |
6.2 to 6.3 |
union { /* changing members, see below */ }; |
10.0 and higher |
Note that in version 6.3 the Timestamp loses the 8-byte alignment that is natural for a LARGE_INTEGER. The purpose will have been to keep the IOP_IRP_EXTENSION no larger than the IO_STACK_LOCATION as a help when building the IRP, the I/O stack locations and the IRP extension as one memory block.
The IO_IRP_EXT_TRACK_OFFSET_HEADER structure is defined in NTIFS.H.
Mask | Definition | Versions |
---|---|---|
0x0001 |
USHORT Allocated : 1; |
6.2 and higher |
0x0002 |
USHORT PropagateId : 1; |
6.2 and higher |
0x0004 |
USHORT TimeStamped : 1; |
6.2 to 6.3 |
USHORT Spare : 13; |
6.2 to 6.3 | |
USHORT SpareBits : 14; |
10.0 and higher |
The Allocated bit is set if the IOP_IRP_EXTENSION is separately allocated from its IRP.
The TypesAllocated word at offset 0x02 is also bit fields. Each bit indicates that the extension has a corresponding type of content. Microsoft’s symbols for these are not known.
Type | Mask | Corresponding Content | Versions |
---|---|---|---|
0 | 0x0001 | ActivityId | 6.2 and higher |
1 | 0x0002 | Timestamp | 6.3 and higher |
2 | 0x0004 | GenericExtension | 6.3 and higher |
3 | 0x0008 | VerifierContext | 6.3 and higher |
4 | 0x0010 | ZeroingOffset | 10.0 and higher |
5 | 0x0020 | FsTrackOffsetBlob and FsTrackedOffset | 10.0 and higher |
6 | 0x0040 | DiskIoAttributionHandle | 1607 and higher |
7 | 0x0080 | AdapterCryptoParameters | 1703 and higher |
Note that types 1, 4, 5 and 7 cannot coexist since the corresponding content for these types are all in the union at the end of the extension.
Offset (x86) | Offset (x64) | Definition | Versions |
---|---|---|---|
0x1C (6.3 to 1511); 0x20 |
0x20 (6.3 to 1511); 0x28 |
LARGE_INTEGER Timestamp; |
10.0 and higher |
ULONG ZeroingOffset; |
10.0 and higher | ||
struct { IO_IRP_EXT_TRACK_OFFSET_HEADER *FsTrackOffsetBlob; LONGLONG FsTrackedOffset; }; |
10.0 and higher | ||
IO_ADAPTER_CRYPTO_PARAMETERS AdapterCryptoParameters; |
1703 and higher |