RTL_PROCESS_LOCK_INFORMATION

The RTL_PROCESS_LOCK_INFORMATION structure is a recurring element in the RTL_PROCESS_LOCKS structure that a successful call to ZwQuerySystemInformation or NtQuerySystemInformation produces at the start of its output buffer when given the information class SystemLocksInformation (0x0C). There is one RTL_PROCESS_LOCK_INFORMATION for each ERESOURCE that is initialised but not yet deleted.

Documentation Status

The RTL_PROCESS_LOCK_INFORMATION structure is not documented.

Microsoft does publish the practical equivalent of a C-language definition as type information in public symbol files, though not for the kernel, where the structure is prepared, nor even for low-level user-mode DLLs that interpret the structure, but for various higher-level user-mode DLLs such as URLMON.DLL and only then starting with version 6.2.

Two earlier disclosures of type information are known, though not in symbol files but in statically linked libraries: GDISRVL.LIB from the Device Driver Kit (DDK) for Windows NT 3.51; and SHELL32.LIB from the DDK for Windows NT 4.0.

Layout

The RTL_PROCESS_LOCK_INFORMATION is 0x24 or 0x30 bytes in 32-bit and 64-bit Windows, respectively, in version 3.51 and higher. The original is 0x3C bytes.

Offset (x86) Offset (x64) Definition Versions Remarks
0x00 (3.10 to 3.50)   unknown dword 3.10 to 3.50  
0x04 (3.10 to 3.50);
0x00
0x00
PVOID Address;
all  
0x08 (3.10 to 3.50)  
ULONG CreatorBackTraceIndex;
3.10 to 3.50 next as USHORT at 0x06
0x0C (3.10 to 3.50);
0x04
0x08
USHORT Type;
all  
0x06 0x0A
USHORT CreatorBackTraceIndex;
3.51 and higher previously ULONG at 0x08
0x0E (3.10 to 3.50)  
USHORT Depth;
3.10 to 3.50  
0x10 (3.10 to 3.50)  
PVOID OwnerBackTrace [4];
3.10 to 3.50  
0x20 (3.10 to 3.50);
0x08
0x10
PVOID OwningThread;
all  
0x24 (3.10 to 3.50);
0x0C
0x18
LONG LockCount;
all  
0x28 (3.10 to 3.50);
0x10
0x1C
ULONG ContentionCount;
all  
0x2C (3.10 to 3.50)   unaccounted four bytes 3.10 to 3.50  
0x14 0x20
ULONG EntryCount;
3.51 and higher  
0x18 0x24
LONG RecursionCount;
3.51 and higher  
0x34 (3.10 to 3.50);
0x1C
0x28
ULONG NumberOfWaitingShared;
all  
0x38 (3.10 to 3.50);
0x20
0x2C
ULONG NumberOfWaitingExclusive;
all  

The unknown dword that begins the structure in its original layout is always zero.

The Address is that of an ERESOURCE from the kernel’s list. This is a kernel-mode address, which is why the SystemLocksInformation case of NtQuerySystemInformation is nowadays failed for restricted callers.

The Type is always 1. Perhaps it was imagined that the SystemLocksInformation might be broadened to other types of lock than the ERESOURCE.

From version 3.50 up to but not including the version 5.2 from Windows Server 2003 SP1, the CreatorBackTraceIndex is always 0. Other versions, both earlier and later, take it from the same-named member of the ERESOURCE. What it is an index into is the kernel’s Stack Trace Database. The indexed entry in this database will have been created when the resource was initialised, given that a particular bit is set in the NtGlobalFlag and that the kernel actually did initialise the database. The required bit is 0x00200000 in versions 3.10 to 3.50 but FLG_KERNEL_STACK_TRACE_DB (0x00002000) in version 3.51 and higher. Microsoft has long documented that this flag “works only when using the checked build of Windows”, and indeed the free builds of versions 3.51 to 5.0 ignore this flag while initialising and therefore never can have a stack trace database for CreatorBackTraceIndex to be non-zero in an ERESOURCE.

The Depth in the original layout is the count of dwords that version 3.10 copies to the OwnerBackTrace array. These names are supposed because the count and dwords come from the Depth and OwnerBackTrace members of the original ERESOURCE. There is no copying in version 3.50: the count is set to zero. Even in version 3.10, no way is yet known that the count can be non-zero in the ERESOURCE.

Though the OwningThread is formally a PVOID, it is not the address of anything but is instead the thread ID. That the RTL_PROCESS_LOCK_INFORMATION has only one OwningThread is because this information structure tells only which thread, if any, has exclusive access to the resource—or, more precisely, had it when the kernel collected the information.

The LockCount is what the ERESOURCE has as its ActiveCount (before version 6.0) or ActiveEntries. It is the number of threads that have access to the resource, i.e., as the exclusive owner or as shared owners.

The unaccounted member at offset 0x2C in the original layout is presumably one of what the much later symbol files present as EntryCount and RecursionCount. No way is yet known that any of these get set in any version.