#ifndef _PH_HANDLEP_H #define _PH_HANDLEP_H #define PH_HANDLE_TABLE_ENTRY_TYPE 0x1 #define PH_HANDLE_TABLE_ENTRY_IN_USE 0x0 #define PH_HANDLE_TABLE_ENTRY_FREE 0x1 // Locked actually means Not Locked. This means that an in use, locked handle table entry can be // used as-is. #define PH_HANDLE_TABLE_ENTRY_LOCKED 0x2 #define PH_HANDLE_TABLE_ENTRY_LOCKED_SHIFT 1 // There is initially one handle table level, with 256 entries. When the handle table is expanded, // the table is replaced with a level 1 table, which contains 256 pointers to level 0 tables (the // first entry already points to the initial level 0 table). Similarly, when the handle table is // expanded a second time, the table is replaced with a level 2 table, which contains 256 pointers // to level 1 tables. // // This provides a maximum of 16,777,216 handles. #define PH_HANDLE_TABLE_LEVEL_ENTRIES 256 #define PH_HANDLE_TABLE_LEVEL_MASK 0x3 #define PH_HANDLE_TABLE_LOCKS 8 #define PH_HANDLE_TABLE_LOCK_INDEX(HandleValue) ((HandleValue) % PH_HANDLE_TABLE_LOCKS) typedef struct _PH_HANDLE_TABLE { PH_QUEUED_LOCK Lock; PH_WAKE_EVENT HandleWakeEvent; ULONG Count; ULONG_PTR TableValue; ULONG FreeValue; ULONG NextValue; ULONG FreeValueAlt; ULONG Flags; PH_QUEUED_LOCK Locks[PH_HANDLE_TABLE_LOCKS]; } PH_HANDLE_TABLE, *PPH_HANDLE_TABLE; FORCEINLINE VOID PhpLockHandleTableShared( _Inout_ PPH_HANDLE_TABLE HandleTable, _In_ ULONG Index ) { PhAcquireQueuedLockShared(&HandleTable->Locks[Index]); } FORCEINLINE VOID PhpUnlockHandleTableShared( _Inout_ PPH_HANDLE_TABLE HandleTable, _In_ ULONG Index ) { PhReleaseQueuedLockShared(&HandleTable->Locks[Index]); } // Handle values work by specifying indicies into each // level. // // Bits 0-7: level 0 // Bits 8-15: level 1 // Bits 16-23: level 2 // Bits 24-31: reserved #define PH_HANDLE_VALUE_INVALID ((ULONG)-1) #define PH_HANDLE_VALUE_SHIFT 2 #define PH_HANDLE_VALUE_BIAS 4 #define PH_HANDLE_VALUE_LEVEL0(HandleValue) ((HandleValue) & 0xff) #define PH_HANDLE_VALUE_LEVEL1_U(HandleValue) ((HandleValue) >> 8) #define PH_HANDLE_VALUE_LEVEL1(HandleValue) (PH_HANDLE_VALUE_LEVEL1_U(HandleValue) & 0xff) #define PH_HANDLE_VALUE_LEVEL2_U(HandleValue) ((HandleValue) >> 16) #define PH_HANDLE_VALUE_LEVEL2(HandleValue) (PH_HANDLE_VALUE_LEVEL2_U(HandleValue) & 0xff) #define PH_HANDLE_VALUE_IS_INVALID(HandleValue) (((HandleValue) >> 24) != 0) FORCEINLINE HANDLE PhpEncodeHandle( _In_ ULONG HandleValue ) { return UlongToHandle(((HandleValue << PH_HANDLE_VALUE_SHIFT) + PH_HANDLE_VALUE_BIAS)); } FORCEINLINE ULONG PhpDecodeHandle( _In_ HANDLE Handle ) { return (HandleToUlong(Handle) - PH_HANDLE_VALUE_BIAS) >> PH_HANDLE_VALUE_SHIFT; } VOID PhpBlockOnLockedHandleTableEntry( _Inout_ PPH_HANDLE_TABLE HandleTable, _In_ PPH_HANDLE_TABLE_ENTRY HandleTableEntry ); PPH_HANDLE_TABLE_ENTRY PhpAllocateHandleTableEntry( _Inout_ PPH_HANDLE_TABLE HandleTable, _Out_ PULONG HandleValue ); VOID PhpFreeHandleTableEntry( _Inout_ PPH_HANDLE_TABLE HandleTable, _In_ ULONG HandleValue, _Inout_ PPH_HANDLE_TABLE_ENTRY HandleTableEntry ); BOOLEAN PhpAllocateMoreHandleTableEntries( _In_ PPH_HANDLE_TABLE HandleTable, _In_ BOOLEAN Initialize ); PPH_HANDLE_TABLE_ENTRY PhpLookupHandleTableEntry( _In_ PPH_HANDLE_TABLE HandleTable, _In_ ULONG HandleValue ); ULONG PhpMoveFreeHandleTableEntries( _Inout_ PPH_HANDLE_TABLE HandleTable ); PPH_HANDLE_TABLE_ENTRY PhpCreateHandleTableLevel0( _In_ PPH_HANDLE_TABLE HandleTable, _In_ BOOLEAN Initialize ); VOID PhpFreeHandleTableLevel0( _In_ PPH_HANDLE_TABLE_ENTRY Table ); PPH_HANDLE_TABLE_ENTRY *PhpCreateHandleTableLevel1( _In_ PPH_HANDLE_TABLE HandleTable ); VOID PhpFreeHandleTableLevel1( _In_ PPH_HANDLE_TABLE_ENTRY *Table ); PPH_HANDLE_TABLE_ENTRY **PhpCreateHandleTableLevel2( _In_ PPH_HANDLE_TABLE HandleTable ); VOID PhpFreeHandleTableLevel2( _In_ PPH_HANDLE_TABLE_ENTRY **Table ); #endif