IOP_IRP_EXTENSION

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.

Variability

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

Layout

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.

Extension Flags

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.

Types

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.

Mutually Exclusive Content

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