EX_X.H

The public symbol file NTKRPAMP.PDB for the original release of Windows 10 tells that the kernel is built with the EX_X.H header at

d:\th\minkernel\ntos\inc

and draws from it the following type definitions:

Line Number Type
34 enum _POOL_TYPE
259 enum _EX_POOL_PRIORITY
997 struct _LOOKASIDE_LIST_EX
1127 struct _NPAGED_LOOKASIDE_LIST
1324 struct _PAGED_LOOKASIDE_LIST
2582 struct _WORK_QUEUE_ITEM
2946 struct _OWNER_ENTRY
2959 struct _ERESOURCE
3502 struct _EX_PUSH_LOCK
3590 struct _EX_PUSH_LOCK_AUTO_EXPAND_STATE
3601 struct _EX_PUSH_LOCK_AUTO_EXPAND
3654 struct _EX_RUNDOWN_REF
3758 struct _EXHANDLE
4020 struct _EXT_DELETE_PARAMETERS

The header EX_X.H is not known in any Device Driver Kit (DDK) or Windows Driver Kit (WDK).

That said, all the types that the kernel is known to pick up from EX_X.H are defined in the standard header WDM.H for kernel-mode programming or in one more header, named NTOSP.H, that Microsoft has mostly kept for its own kernel-mode programming but which is available from inspection because of its disclosure in the “minwin” directory of the Windows 10 WDK for the original release and for Version 1511.

Most of the types are extracted to both the widely available WDM.H and the private NTOSP.H, but both miss at least some lines and WDM.H consistently misses more. Some accounting is possible on the assumption that although each of these headers receives only a selection of lines from EX_X.H, their selections are contiguous. Put another way, assume that WDM.H lines 21560 to 23583 and NTOSP.H lines 16296 to 20137 are generated only as extractions from EX_X.H. Then some of the EX_X.H material that goes to NTOSP.H but not to WDM.H goes to NTDDK.H or NTIFS.H instead, but most is otherwise unknown in the WDK headers.

Reconstruction

This presumably accidental publication of NTOSP.H allows for high confidence in reconstructing the unseen EX_X.H almost completely. It may be that content is extracted from EX_X.H into the standard headers. It may be that all are extracted from yet some other source. Eithe way, the assumption seems reasonable that each line in the unseen EX_X.H is duplicated in zero or more of the published headers in an order-preserving way, leaving each of the published headers with a contiguous region of lines that can each be inferred as being also in the unseen EX_X.H.

In the table that follows, the line numbers on the left are deduced from type information in a statically linked library named CLFSMGMT.LIB which Microsoft publishes with the Software Development Kit (SDK) as if for user-mode programming. Of all sources of type information that cites EX_X.H as the header from which the compiler obtained the definitions, this is presently the one that is known to have it for the most types. The line numbers on the right are from headers as published in the WDK.  

Line Number Type WDM.H NTDDK.H NTOSP.H NTOSIFS.H
34 enum _POOL_TYPE 21560   16296  
259 enum _EX_POOL_PRIORITY 21773   16519  
997 struct _LOOKASIDE_LIST_EX 22401   17204  
1127 struct _NPAGED_LOOKASIDE_LIST 22531   17334  
1324 struct _PAGED_LOOKASIDE_LIST 22728   17531  
2559 enum _WORK_QUEUE_TYPE 22966   18750  
2582 struct _WORK_QUEUE_ITEM 22989   18773  
2669 struct _ZONE_SEGMENT_HEADER   8244 18854  
2674 struct _ZONE_HEADER   8249 18859  
2946 struct _OWNER_ENTRY 23058   19129  
2948 anonymous union in
struct _OWNER_ENTRY
23060   19131  
2949 anonymous struct in
anonymous union in
struct _OWNER_ENTRY
23061   19132  
2959 struct _ERESOURCE 23071   19142  
2971 anonymous union in
struct _ERESOURCE
23083   19154  
2973 anonymous struct in
anonymous union in
struct _ERESOURCE
23085   19156  
3002 anonymous union in
struct _ERESOURCE
23114   19185  
3020 struct _RESOURCE_HASH_ENTRY 23132   19203  
3027 struct _RESOURCE_PERFORMANCE_DATA 23139   19210  
3502 struct _EX_PUSH_LOCK     19630 100
3537 anonymous union in
struct _EX_PUSH_LOCK
    19665 135
3538 anonymous struct in
anonymous union in
struct _EX_PUSH_LOCK
    19666 136
3559 struct _EX_PUSH_LOCK_CACHE_AWARE_LEGACY     19687 157
3567 struct _EX_PUSH_LOCK_CACHE_AWARE_PADDED     19695 165
3569 anonymous union in
struct _EX_PUSH_LOCK_CACHE_AWARE_PADDED
    19697 167
3571 anonymous struct in
anonymous union in
struct _EX_PUSH_LOCK_CACHE_AWARE_PADDED
    19699 169
3590 struct _EX_PUSH_LOCK_AUTO_EXPAND_STATE     19718 188
3591 anonymous union in
struct _EX_PUSH_LOCK_AUTO_EXPAND_STATE
    19719 189
3592 anonymous struct in
anonymous union in
struct _EX_PUSH_LOCK_AUTO_EXPAND_STATE
    19720 190
3601 struct _EX_PUSH_LOCK_AUTO_EXPAND     19729 199
3654 struct _EX_RUNDOWN_REF 23460   19780  
3660 anonymous union in
struct _EX_RUNDOWN_REF
23466   19786  
3689 struct _EX_RUNDOWN_REF_CACHE_AWARE_STATE     19815  
3690 anonymous union in
struct _EX_RUNDOWN_REF_CACHE_AWARE_STATE
    19816  
3691 anonymous struct in
anonymous union in
struct _EX_RUNDOWN_REF_CACHE_AWARE_STATE
    19817  
3712 struct _EX_RUNDOWN_REF_CACHE_AWARE     19838  
3758 struct _EXHANDLE     19884  
3760 anonymous union in
struct _EXHANDLE
    19886  
3762 anonymous struct in
anonymous union in
struct _EXHANDLE
    19888  
4020 struct _EXT_DELETE_PARAMETERS 23583   20137  
5908 enum _LICENSING_TAMPER_STATE     21941  
5974 anonymous enum     22007  
6011 struct _EX_EXTENSION_REGISTRATION_1     22041 1345
6080 struct EX_BOOT_DEVICE_HANDLE_        
6088 struct _EX_BOOT_DEVICE_REGISTRATION     22114  

For an example of what can be learnt from this skeleton for reconstruction, consider what might be in the 1,235 lines between the opening braces for definitions of _PAGED_LOOKASIDE_LIST and _WORK_QUEUE_TYPE. Only 223 are duplicated in WDM.H. This would be better than nothing, but NTOSP.H has 1,219 lines in this space. It’s all but certain that every one of them is in the corresponding space in EX_X.H. Thus is this part of the unseen EX_X.H reconstructed almost completely from published material.

A small but useful outcome of just this part of the reconstruction is to place the numerous small inline routines that are frequently encountered in any debugging or reverse engineering of Microsoft’s kernel-mode code—not only in the kernel itself—that works with user-mode addresses. Such addresses are well-known to require careful handling—or are not known nearly well enough, depending on perspective. The kernel exports functions named ProbeForRead and ProbeForWrite that help with one aspect of this care, but Microsoft’s own kernel-mode programmers have these as macros and have long benefited from the use of many inline elaborations that are specialised to probing for particular types and small structures. It must make their code more readable.

Debugging their code, including from outside Microsoft, is similarly much easier for recognising the macros and the inlining. Because of this, the inline routines must have attracted attention from very early in any study of kernel-mode Windows that’s worth calling a study. They will have been well-known long before the presumably accidental publication of NTOSP.H. Not only does their inline usage get them named in the kernel’s public symbol files starting with Windows 8, but they are named in older symbol files from having sometimes been instantiated instead of inlined. What was not known (without source-code access) until the NTOSP.H disclosure is which header provides the kernel with these macros and inline routines.

Is it vital to know that the kernel gets them from an unpublished header named EX_X.H? Not for itself, of course not. Does it help with an understanding of how Windows, still by far the world’s most sophisticated operating system in general use, is organised? In its small way, yes.