2025-05-13 19:45:22 +03:00

148 lines
4.0 KiB
C

#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