an approach to list all mutex in windows system.

I found two reference books which are useful in system internal programming: Windows NT-2000 Native API Reference_ _and Undocumented Windows NT.

My approach below is copied from sample in book Windows NT-2000 Native API Reference, it lists all system Mutex by tracking Mutex created per process, the 1st part declares all depend structures and methods, then the 2nd part shows a sample usage.

Hope this article be helpful to guys who have such requirement in their apps, any discussions followed up are welcome!

Declarations

#pragma warning (disable:4005)
#include <windows.h>
#include <stdio.h>
#include <ntstatus.h>
#pragma warning (default:4005)
 
///////////////////////////////////////////////////////////////////////
 
typedef struct _LSA_UNICODE_STRING {
    USHORT Length;
    USHORT MaximumLength;
    PWSTR  Buffer;
} LSA_UNICODE_STRING, PLSA_UNICODE_STRING, UNICODE_STRING, PUNICODE_STRING; 
 
typedef struct _OBJECT_NAME_INFORMATION { 
    UNICODE_STRING Name;
} OBJECT_NAME_INFORMATION, POBJECT_NAME_INFORMATION;
 
typedef enum _POOL_TYPE {
    NonPagedPool,
    PagedPool,
    NonPagedPoolMustSucceed,
    DontUseThisType,
    NonPagedPoolCacheAligned,
    PagedPoolCacheAligned,
    NonPagedPoolCacheAlignedMustS,
    MaxPoolType,
    NonPagedPoolSession = 32,
    PagedPoolSession,
    NonPagedPoolMustSucceedSession,
    DontUseThisTypeSession,
    NonPagedPoolCacheAlignedSession,
    PagedPoolCacheAlignedSession,
    NonPagedPoolCacheAlignedMustSSession
} POOL_TYPE;
 
typedef enum _SYSTEM_INFORMATION_CLASS {
    SystemHandleInformation = 16,
} SYSTEM_INFORMATION_CLASS;
 
typedef struct  _SYSTEM_HANDLE_INFORMATION {
    ULONG       ProcessId;
    UCHAR       ObjectTypeNumber;
    UCHAR       Flags;
    USHORT      Handle;
    PVOID       Object;
    ACCESS_MASK GrantedAccess;
} SYSTEM_HANDLE_INFORMATION,  PSYSTEM_HANDLE_INFORMATION;
 
typedef enum _OBJECT_INFORMATION_CLASS {
    ObjectBasicInformation,
    ObjectNameInformation,
    ObjectTypeInformation,
    ObjectAllTypesInformation,
    ObjectHandleInformation
} OBJECT_INFORMATION_CLASS;
 
typedef struct  _OBJECT_BASIC_INFORMATION {
    ULONG           Attributes;
    ACCESS_MASK     GrantedAccess;
    ULONG           HandleCount;
    ULONG           PointerCount;
    ULONG           PagedPoolUsage;
    ULONG           NonPagedPoolUsage;
    ULONG           Reserved    [   3];
    ULONG           NameInformationLength;
    ULONG           TypeInformationLength;
    ULONG           SecurityDescriptorLength;
    LARGE_INTEGER   CreateTime;
} OBJECT_BASIC_INFORMATION,   POBJECT_BASIC_INFORMATION;
 
typedef struct  _OBJECT_TYPE_INFORMATION {
    UNICODE_STRING  Name;
    ULONG           ObjectCount;
    ULONG           HandleCount;
    ULONG           Reserved1   [   4];
    ULONG           PeakObjectCount;
    ULONG           PeakHandleCount;
    ULONG           Reserved2   [   4];
    ULONG           InvalidAttributes;
    GENERIC_MAPPING GenericMapping;
    ULONG           ValidAccess;
    UCHAR           Unknown;
    BOOLEAN         MaintainHandleDatabase;
    POOL_TYPE        PoolType;
    ULONG           PagedPoolUsage;
    ULONG           NonPagedPoolUsage;
} OBJECT_TYPE_INFORMATION,    POBJECT_TYPE_INFORMATION;
 
typedef NTSTATUS (_stdcall PZWQUERYSYSTEMINFORMATION) (
    SYSTEM_INFORMATION_CLASS,
    PVOID,
    ULONG,
    PULONG
);
 
typedef NTSTATUS (_stdcall PZWDUPLICATEOBJECT) (
    HANDLE,
    HANDLE,
    HANDLE,
    PHANDLE,
    ACCESS_MASK,
    ULONG,
    ULONG
);
 
typedef NTSTATUS (_stdcall *PZWQUERYOBJECT) (
    HANDLE,
    OBJECT_INFORMATION_CLASS,
    PVOID,
    ULONG,
    PULONG
);
 
#define NT_SUCCESS(Status) ((NTSTATUS)(Status) >= 0)
#define DUPLICATE_SAME_ATTRIBUTES   0x00000004 
#define NtCurrentProcess() ( (HANDLE) -1 )
 
///////////////////////////////////////////////////////////////////////
 
BOOL EnablePrivilege(LPCWSTR name)
{
    TOKEN_PRIVILEGES priv = {1, {0, 0, SE_PRIVILEGE_ENABLED}};
    LookupPrivilegeValue(0, name, &priv.Privileges[0].Luid);
 
    HANDLE hToken;
    OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken);
 
    AdjustTokenPrivileges(hToken, FALSE, &priv, sizeof priv, 0, 0);
    BOOL rv = GetLastError() == ERROR_SUCCESS;
 
    CloseHandle(hToken);
    return rv;
}

Sample Usage

// Test method for listing all mutex per process.
int main(int argc, char argv[])
{
    // provide your process id here.
    ULONG pid = 612;
 
    // adjuat process privileges.
    EnablePrivilege(SE_DEBUG_NAME);
 
    // load dll into memory.
    HMODULE hNtDll = LoadLibrary(TEXT(“ntdll.dll”));
    if (!hNtDll) return 0;
 
    // initial undocumented apis.
    PZWQUERYSYSTEMINFORMATION ZwQuerySystemInformation = 
        (PZWQUERYSYSTEMINFORMATION)GetProcAddress(hNtDll, “ZwQuerySystemInformation”);
    PZWDUPLICATEOBJECT ZwDuplicateObject = 
        (PZWDUPLICATEOBJECT)GetProcAddress(hNtDll, “ZwDuplicateObject”);
    PZWQUERYOBJECT ZwQueryObject = 
        (PZWQUERYOBJECT)GetProcAddress(hNtDll, “ZwQueryObject”);
 
    // get system info, list all process info.
    ULONG n = 0x1000;
    PULONG p = new ULONG[n];
    while (ZwQuerySystemInformation(SystemHandleInformation, p, n  sizeof p, 0)
           == STATUS_INFO_LENGTH_MISMATCH)
        delete [] p, p = new ULONG[n = 2];
    PSYSTEM_HANDLE_INFORMATION h = PSYSTEM_HANDLE_INFORMATION(p + 1);
 
    // try to find target process by matching process id.
    for (ULONG i = 0; i < p; i++) 
    {
        if (h[i].ProcessId == pid)
        {    
            HANDLE hObject;
            HANDLE hProcess = OpenProcess(PROCESS_DUP_HANDLE, FALSE, pid);
 
            if (ZwDuplicateObject(hProcess, HANDLE(h[i].Handle), NtCurrentProcess(), 
                    &hObject, 0, 0, DUPLICATE_SAME_ATTRIBUTES)!= STATUS_SUCCESS) 
                continue;
 
            // print basic info of this process.
            OBJECT_BASIC_INFORMATION obi;
            ZwQueryObject(hObject, ObjectBasicInformation, &obi, sizeof obi, &n);
            printf(“%p %ld %04hx %6lx %2x %3lx %3ld %4ld “,
                   h[i].Object, h[i].ProcessId, h[i].Handle, h[i].GrantedAccess,
                   int(h[i].Flags), obi.Attributes,
                   obi.HandleCount - 1, obi.PointerCount - 2);
 
            // print type info of this process.
            n = obi.TypeInformationLength + 2;
            POBJECT_TYPE_INFORMATION oti = POBJECT_TYPE_INFORMATION(new CHAR[n]);
            ZwQueryObject(hObject, ObjectTypeInformation, oti, n, &n);
            printf(“%-14.ws “, oti[0].Name.Length / 2, oti[0].Name.Buffer);
 
            // print name info of this process.
            n = obi.NameInformationLength == 0
                ? MAX_PATH  sizeof (WCHAR) : obi.NameInformationLength;
            POBJECT_NAME_INFORMATION oni = POBJECT_NAME_INFORMATION(new CHAR[n]);
            NTSTATUS rv = ZwQueryObject(hObject, ObjectNameInformation, oni, n, &n);
            if (NT_SUCCESS(rv))
                printf(“%.ws”, oni[0].Name.Length / 2, oni[0].Name.Buffer);
 
            // close handles.
            printf(“n”);
            CloseHandle(hObject);
            CloseHandle(hProcess);              
        }
    }
    delete [] p;
    return 0;
}