How to get the list of critical sections in a process

windbg

Solution

This is relatively straighforward, you need to use structure called RTL_CRITICAL_SECTION_DEBUG. I added my annotations in the printout:

0:011> dt ntdll!_RTL_CRITICAL_SECTION_DEBUG
   +0x000 Type             : Uint2B
   +0x002 CreatorBackTraceIndex : Uint2B
   +0x004 CriticalSection  : Ptr32 _RTL_CRITICAL_SECTION  // This is pointer to actual critical section
   +0x008 ProcessLocksList : _LIST_ENTRY  // All critical sections are chained in this doubly linked list
   +0x010 EntryCount       : Uint4B
   +0x014 ContentionCount  : Uint4B
   +0x018 Flags            : Uint4B
   +0x01c CreatorBackTraceIndexHigh : Uint2B
   +0x01e SpareUSHORT      : Uint2B

As you can see, all critical sections belong to the same global list, with `ProcessLocksList` of one critical section pointing to to `ProcessLocksList` of next critical section (as well as to the previous). Once you know addresses of all `ProcessLocksList`s, you can extract pointer to RTL_CRITICAL_SECTION structure by substracting sizeof(void*) from it.

Finally, the address of very first `ProcessLocksList` entry is given by ntdll!RtlCriticalSectionList.

The following command is a demonstration of what I said above. It will print out all critical sections in the process:

  !list "-t ntdll!_LIST_ENTRY.Flink -e -x \"ln poi(@$extret-0x4); dt ntdll!_RTL_CRITICAL_SECTION poi(@$extret-0x4)\" ntdll!RtlCriticalSectionList"

Make adjustments for x64 if you need one.

ADDED AS REQUESTED: Here is a version for x64:

  !list "-t ntdll!_LIST_ENTRY.Flink -e -x \"ln poi(@$extret-0x8); dt ntdll!_RTL_CRITICAL_SECTION poi(@$extret-0x8)\" ntdll!RtlCriticalSectionList"

Problem

In WinDbg, you can call !locks to get the list of all critical sections in the current process. I wonder whether there is a way to call a debug engine API to retrieve the same list. I want to do it in a custom built debugger built in C++, which is built on Debug Engine APIs. Any thoughts? Thanks a lot.

Original source