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.