Handles - Introduction

Addendum

In Windows, a handle is an opaque value representing a reference to a specific object (file, process, thread, etc.). All handles are managed in a structure called a handle table. Handle values are efficiently recycled.

The handle table is three-tiered:

Only the subhandle table is allocated initially. Higher tiers are created as needed.

Handle Table Hierarchy

source: Windows Internals 7, part 2


Key Windows Kernel Structures

_HANDLE_TABLE_ENTRY

Describes a handle in memory. The TableCode field in _HANDLE_TABLE points to the table of these entries.

// 0x10 bytes (sizeof)
union _HANDLE_TABLE_ENTRY {
    volatile LONGLONG VolatileLowValue;
    LONGLONG LowValue;
    struct {
        struct _HANDLE_TABLE_ENTRY_INFO* volatile InfoTable;
        LONGLONG HighValue;
        union _HANDLE_TABLE_ENTRY* NextFreeHandleEntry;
        struct _EXHANDLE LeafHandleValue;
    };
    LONGLONG RefCountField;
    ULONGLONG Unlocked:1;
    ULONGLONG RefCnt:16;
    ULONGLONG Attributes:3;
    struct {
        ULONGLONG ObjectPointerBits:44;
        ULONG GrantedAccessBits:25;
        ULONG NoRightsUpgrade:1;
        ULONG Spare1:6;
    };
    ULONG Spare2;
};

_HANDLE_TABLE

Tracks and manages all handles in a process. It is referenced in the ObjectTable field of EPROCESS.

// 0x80 bytes (sizeof)
struct _HANDLE_TABLE {
    ULONG NextHandleNeedingPool;
    LONG ExtraInfoPages;
    volatile ULONGLONG TableCode;
    struct _EPROCESS* QuotaProcess;
    struct _LIST_ENTRY HandleTableList;
    ULONG UniqueProcessId;
    union {
        ULONG Flags;
        struct {
            UCHAR StrictFIFO:1;
            UCHAR EnableHandleExceptions:1;
            UCHAR Rundown:1;
            UCHAR Duplicated:1;
            UCHAR RaiseUMExceptionOnInvalidHandleClose:1;
        };
    };
    struct _EX_PUSH_LOCK HandleContentionEvent;
    struct _EX_PUSH_LOCK HandleTableLock;
    union {
        struct _HANDLE_TABLE_FREE_LIST FreeLists[1];
        struct {
            UCHAR ActualEntry[32];
            struct _HANDLE_TRACE_DEBUG_INFO* DebugInfo;
        };
    };
};

_OBJECT_HEADER

This structure precedes every kernel object, providing metadata like reference count and object type.

//0x38 bytes (sizeof), src: Vergilius Project
struct _OBJECT_HEADER
{
    LONGLONG PointerCount;                                                  //0x0
    union
    {
        LONGLONG HandleCount;                                               //0x8
        VOID* NextToFree;                                                   //0x8
    };
    struct _EX_PUSH_LOCK Lock;                                              //0x10
    UCHAR TypeIndex;                                                        //0x18
    union
    {
        UCHAR TraceFlags;                                                   //0x19
        struct
        {
            UCHAR DbgRefTrace:1;                                            //0x19
            UCHAR DbgTracePermanent:1;                                      //0x19
        };
    };
    UCHAR InfoMask;                                                         //0x1a
    union
    {
        UCHAR Flags;                                                        //0x1b
        struct
        {
            UCHAR NewObject:1;                                              //0x1b
            UCHAR KernelObject:1;                                           //0x1b
            UCHAR KernelOnlyAccess:1;                                       //0x1b
            UCHAR ExclusiveObject:1;                                        //0x1b
            UCHAR PermanentObject:1;                                        //0x1b
            UCHAR DefaultSecurityQuota:1;                                   //0x1b
            UCHAR SingleHandleEntry:1;                                      //0x1b
            UCHAR DeletedInline:1;                                          //0x1b
        };
    };
    ULONG Reserved;                                                         //0x1c
    union
    {
        struct _OBJECT_CREATE_INFORMATION* ObjectCreateInfo;                //0x20
        VOID* QuotaBlockCharged;                                            //0x20
    };
    VOID* SecurityDescriptor;                                               //0x28
    struct _QUAD Body;                                                      //0x30
};