ReactOS 0.4.15-dev-7942-gd23573b
handle.c File Reference
#include <ntoskrnl.h>
#include <debug.h>
Include dependency graph for handle.c:

Go to the source code of this file.

Macros

#define NDEBUG
 
#define SizeOfHandle(x)   (sizeof(HANDLE) * (x))
 
#define INDEX_TO_HANDLE_VALUE(x)   ((x) << HANDLE_TAG_BITS)
 
#define strtoulptr   strtoul
 

Functions

VOID NTAPI ExpInitializeHandleTables (VOID)
 
PHANDLE_TABLE_ENTRY NTAPI ExpLookupHandleTableEntry (IN PHANDLE_TABLE HandleTable, IN EXHANDLE Handle)
 
PVOID NTAPI ExpAllocateTablePagedPool (IN PEPROCESS Process OPTIONAL, IN SIZE_T Size)
 
PVOID NTAPI ExpAllocateTablePagedPoolNoZero (IN PEPROCESS Process OPTIONAL, IN SIZE_T Size)
 
VOID NTAPI ExpFreeTablePagedPool (IN PEPROCESS Process OPTIONAL, IN PVOID Buffer, IN SIZE_T Size)
 
VOID NTAPI ExpFreeLowLevelTable (IN PEPROCESS Process, IN PHANDLE_TABLE_ENTRY TableEntry)
 
VOID NTAPI ExpFreeHandleTable (IN PHANDLE_TABLE HandleTable)
 
VOID NTAPI ExpFreeHandleTableEntry (IN PHANDLE_TABLE HandleTable, IN EXHANDLE Handle, IN PHANDLE_TABLE_ENTRY HandleTableEntry)
 
PHANDLE_TABLE NTAPI ExpAllocateHandleTable (IN PEPROCESS Process OPTIONAL, IN BOOLEAN NewTable)
 
PHANDLE_TABLE_ENTRY NTAPI ExpAllocateLowLevelTable (IN PHANDLE_TABLE HandleTable, IN BOOLEAN DoInit)
 
PHANDLE_TABLE_ENTRY *NTAPI ExpAllocateMidLevelTable (IN PHANDLE_TABLE HandleTable, IN BOOLEAN DoInit, OUT PHANDLE_TABLE_ENTRY *LowTableEntry)
 
BOOLEAN NTAPI ExpAllocateHandleTableEntrySlow (IN PHANDLE_TABLE HandleTable, IN BOOLEAN DoInit)
 
ULONG NTAPI ExpMoveFreeHandles (IN PHANDLE_TABLE HandleTable)
 
PHANDLE_TABLE_ENTRY NTAPI ExpAllocateHandleTableEntry (IN PHANDLE_TABLE HandleTable, OUT PEXHANDLE NewHandle)
 
PHANDLE_TABLE NTAPI ExCreateHandleTable (IN PEPROCESS Process OPTIONAL)
 
HANDLE NTAPI ExCreateHandle (IN PHANDLE_TABLE HandleTable, IN PHANDLE_TABLE_ENTRY HandleTableEntry)
 
VOID NTAPI ExpBlockOnLockedHandleEntry (IN PHANDLE_TABLE HandleTable, IN PHANDLE_TABLE_ENTRY HandleTableEntry)
 
BOOLEAN NTAPI ExpLockHandleTableEntry (IN PHANDLE_TABLE HandleTable, IN PHANDLE_TABLE_ENTRY HandleTableEntry)
 
VOID NTAPI ExUnlockHandleTableEntry (IN PHANDLE_TABLE HandleTable, IN PHANDLE_TABLE_ENTRY HandleTableEntry)
 
VOID NTAPI ExRemoveHandleTable (IN PHANDLE_TABLE HandleTable)
 
VOID NTAPI ExDestroyHandleTable (IN PHANDLE_TABLE HandleTable, IN PVOID DestroyHandleProcedure OPTIONAL)
 
BOOLEAN NTAPI ExDestroyHandle (IN PHANDLE_TABLE HandleTable, IN HANDLE Handle, IN PHANDLE_TABLE_ENTRY HandleTableEntry OPTIONAL)
 
PHANDLE_TABLE_ENTRY NTAPI ExMapHandleToPointer (IN PHANDLE_TABLE HandleTable, IN HANDLE Handle)
 
PHANDLE_TABLE NTAPI ExDupHandleTable (IN PEPROCESS Process, IN PHANDLE_TABLE HandleTable, IN PEX_DUPLICATE_HANDLE_CALLBACK DupHandleProcedure, IN ULONG_PTR Mask)
 
BOOLEAN NTAPI ExChangeHandle (IN PHANDLE_TABLE HandleTable, IN HANDLE Handle, IN PEX_CHANGE_HANDLE_CALLBACK ChangeRoutine, IN ULONG_PTR Context)
 
VOID NTAPI ExSweepHandleTable (IN PHANDLE_TABLE HandleTable, IN PEX_SWEEP_HANDLE_CALLBACK EnumHandleProcedure, IN PVOID Context)
 
BOOLEAN NTAPI ExEnumHandleTable (IN PHANDLE_TABLE HandleTable, IN PEX_ENUM_HANDLE_CALLBACK EnumHandleProcedure, IN OUT PVOID Context, OUT PHANDLE EnumHandle OPTIONAL)
 

Variables

LIST_ENTRY HandleTableListHead
 
EX_PUSH_LOCK HandleTableListLock
 

Macro Definition Documentation

◆ INDEX_TO_HANDLE_VALUE

#define INDEX_TO_HANDLE_VALUE (   x)    ((x) << HANDLE_TAG_BITS)

Definition at line 21 of file handle.c.

◆ NDEBUG

#define NDEBUG

Definition at line 13 of file handle.c.

◆ SizeOfHandle

#define SizeOfHandle (   x)    (sizeof(HANDLE) * (x))

Definition at line 20 of file handle.c.

◆ strtoulptr

#define strtoulptr   strtoul

Definition at line 28 of file handle.c.

Function Documentation

◆ ExChangeHandle()

BOOLEAN NTAPI ExChangeHandle ( IN PHANDLE_TABLE  HandleTable,
IN HANDLE  Handle,
IN PEX_CHANGE_HANDLE_CALLBACK  ChangeRoutine,
IN ULONG_PTR  Context 
)

Definition at line 1189 of file handle.c.

1193{
1194 EXHANDLE ExHandle;
1195 PHANDLE_TABLE_ENTRY HandleTableEntry;
1197 PAGED_CODE();
1198
1199 /* Set the handle value */
1200 ExHandle.GenericHandleOverlay = Handle;
1201
1202 /* Find the entry for this handle */
1203 HandleTableEntry = ExpLookupHandleTableEntry(HandleTable, ExHandle);
1204
1205 /* Make sure that we found an entry, and that it's valid */
1206 if (!(HandleTableEntry) ||
1207 !(HandleTableEntry->Object) ||
1208 (HandleTableEntry->NextFreeTableEntry == -2))
1209 {
1210 /* It isn't, fail */
1211 return FALSE;
1212 }
1213
1214 /* Enter a critical region */
1216
1217 /* Try locking the handle entry */
1218 if (ExpLockHandleTableEntry(HandleTable, HandleTableEntry))
1219 {
1220 /* Call the change routine and unlock the entry */
1221 Result = ChangeRoutine(HandleTableEntry, Context);
1222 ExUnlockHandleTableEntry(HandleTable, HandleTableEntry);
1223 }
1224
1225 /* Leave the critical region and return the callback result */
1227 return Result;
1228}
#define PAGED_CODE()
unsigned char BOOLEAN
#define FALSE
Definition: types.h:117
ULONG Handle
Definition: gdb_input.c:15
static XMS_HANDLE HandleTable[XMS_MAX_HANDLES]
Definition: himem.c:83
#define KeLeaveCriticalRegion()
Definition: ke_x.h:119
#define KeEnterCriticalRegion()
Definition: ke_x.h:88
PHANDLE_TABLE_ENTRY NTAPI ExpLookupHandleTableEntry(IN PHANDLE_TABLE HandleTable, IN EXHANDLE Handle)
Definition: handle.c:43
BOOLEAN NTAPI ExpLockHandleTableEntry(IN PHANDLE_TABLE HandleTable, IN PHANDLE_TABLE_ENTRY HandleTableEntry)
Definition: handle.c:884
VOID NTAPI ExUnlockHandleTableEntry(IN PHANDLE_TABLE HandleTable, IN PHANDLE_TABLE_ENTRY HandleTableEntry)
Definition: handle.c:923
Definition: extypes.h:596
PVOID Object
Definition: extypes.h:599
LONG NextFreeTableEntry
Definition: extypes.h:612
Definition: ex.h:87
HANDLE GenericHandleOverlay
Definition: ex.h:102
_At_(*)(_In_ PWSK_CLIENT Client, _In_opt_ PUNICODE_STRING NodeName, _In_opt_ PUNICODE_STRING ServiceName, _In_opt_ ULONG NameSpace, _In_opt_ GUID *Provider, _In_opt_ PADDRINFOEXW Hints, _Outptr_ PADDRINFOEXW *Result, _In_opt_ PEPROCESS OwningProcess, _In_opt_ PETHREAD OwningThread, _Inout_ PIRP Irp Result)(Mem)) NTSTATUS(WSKAPI *PFN_WSK_GET_ADDRESS_INFO
Definition: wsk.h:409

Referenced by NtSetInformationObject(), and ObSetHandleAttributes().

◆ ExCreateHandle()

HANDLE NTAPI ExCreateHandle ( IN PHANDLE_TABLE  HandleTable,
IN PHANDLE_TABLE_ENTRY  HandleTableEntry 
)

Definition at line 827 of file handle.c.

829{
831 PHANDLE_TABLE_ENTRY NewEntry;
832 PAGED_CODE();
833
834 /* Start with a clean handle */
835 Handle.GenericHandleOverlay = NULL;
836
837 /* Allocate a new entry */
839 if (NewEntry)
840 {
841 /* Enter a critical region */
843
844 /* Write the entry */
845 *NewEntry = *HandleTableEntry;
846
847 /* Unlock it and leave the critical region */
850 }
851
852 /* Return the handle value */
853 return Handle.GenericHandleOverlay;
854}
#define NULL
Definition: types.h:112
PHANDLE_TABLE_ENTRY NTAPI ExpAllocateHandleTableEntry(IN PHANDLE_TABLE HandleTable, OUT PEXHANDLE NewHandle)
Definition: handle.c:683

Referenced by ObDuplicateObject(), ObpCreateHandle(), ObpCreateUnnamedHandle(), PspCreateProcess(), PspCreateThread(), and RtlpCreateAtomHandle().

◆ ExCreateHandleTable()

PHANDLE_TABLE NTAPI ExCreateHandleTable ( IN PEPROCESS Process  OPTIONAL)

Definition at line 801 of file handle.c.

802{
804 PAGED_CODE();
805
806 /* Allocate the handle table */
808 if (!HandleTable) return NULL;
809
810 /* Acquire the handle table lock */
813
814 /* Insert it into the list */
816
817 /* Release the lock */
820
821 /* Return the handle table */
822 return HandleTable;
823}
#define TRUE
Definition: types.h:120
#define InsertTailList(ListHead, Entry)
FORCEINLINE VOID ExAcquirePushLockExclusive(PEX_PUSH_LOCK PushLock)
Definition: ex.h:1036
FORCEINLINE VOID ExReleasePushLockExclusive(PEX_PUSH_LOCK PushLock)
Definition: ex.h:1252
_Must_inspect_result_ _In_ PLARGE_INTEGER _In_ PLARGE_INTEGER _In_ ULONG _In_ PFILE_OBJECT _In_ PVOID Process
Definition: fsrtlfuncs.h:223
PHANDLE_TABLE NTAPI ExpAllocateHandleTable(IN PEPROCESS Process OPTIONAL, IN BOOLEAN NewTable)
Definition: handle.c:331
EX_PUSH_LOCK HandleTableListLock
Definition: handle.c:19
LIST_ENTRY HandleTableListHead
Definition: handle.c:18

Referenced by ObInitProcess(), ObInitSystem(), PspInitPhase0(), and RtlpCreateAtomHandleTable().

◆ ExDestroyHandle()

BOOLEAN NTAPI ExDestroyHandle ( IN PHANDLE_TABLE  HandleTable,
IN HANDLE  Handle,
IN PHANDLE_TABLE_ENTRY HandleTableEntry  OPTIONAL 
)

Definition at line 984 of file handle.c.

987{
988 EXHANDLE ExHandle;
990 PAGED_CODE();
991
992 /* Setup the actual handle value */
993 ExHandle.GenericHandleOverlay = Handle;
994
995 /* Enter a critical region and check if we have to lookup the handle */
997 if (!HandleTableEntry)
998 {
999 /* Lookup the entry */
1000 HandleTableEntry = ExpLookupHandleTableEntry(HandleTable, ExHandle);
1001
1002 /* Make sure that we found an entry, and that it's valid */
1003 if (!(HandleTableEntry) ||
1004 !(HandleTableEntry->Object) ||
1005 (HandleTableEntry->NextFreeTableEntry == -2))
1006 {
1007 /* Invalid handle, fail */
1009 return FALSE;
1010 }
1011
1012 /* Lock the entry */
1013 if (!ExpLockHandleTableEntry(HandleTable, HandleTableEntry))
1014 {
1015 /* Couldn't lock, fail */
1017 return FALSE;
1018 }
1019 }
1020 else
1021 {
1022 /* Make sure the handle is locked */
1023 ASSERT((HandleTableEntry->Value & EXHANDLE_TABLE_ENTRY_LOCK_BIT) == 0);
1024 }
1025
1026 /* Clear the handle */
1027 Object = InterlockedExchangePointer((PVOID*)&HandleTableEntry->Object, NULL);
1028
1029 /* Sanity checks */
1030 ASSERT(Object != NULL);
1032
1033 /* Unblock the pushlock */
1034 ExfUnblockPushLock(&HandleTable->HandleContentionEvent, NULL);
1035
1036 /* Free the actual entry */
1037 ExpFreeHandleTableEntry(HandleTable, ExHandle, HandleTableEntry);
1038
1039 /* If we got here, return success */
1041 return TRUE;
1042}
#define InterlockedExchangePointer(Target, Value)
Definition: dshow.h:45
#define EXHANDLE_TABLE_ENTRY_LOCK_BIT
Definition: ex.h:146
#define ASSERT(a)
Definition: mode.c:44
VOID NTAPI ExpFreeHandleTableEntry(IN PHANDLE_TABLE HandleTable, IN EXHANDLE Handle, IN PHANDLE_TABLE_ENTRY HandleTableEntry)
Definition: handle.c:279
VOID FASTCALL ExfUnblockPushLock(PEX_PUSH_LOCK PushLock, PVOID CurrentWaitBlock)
Definition: pushlock.c:1205
uint32_t ULONG_PTR
Definition: typedefs.h:65
_Must_inspect_result_ _In_ WDFCOLLECTION _In_ WDFOBJECT Object

Referenced by ObpCloseHandleTableEntry(), PspDeleteProcess(), PspDeleteThread(), RtlpCloseHandleCallback(), RtlpCreateAtomHandle(), and RtlpFreeAtomHandle().

◆ ExDestroyHandleTable()

VOID NTAPI ExDestroyHandleTable ( IN PHANDLE_TABLE  HandleTable,
IN PVOID DestroyHandleProcedure  OPTIONAL 
)

Definition at line 963 of file handle.c.

965{
966 PAGED_CODE();
967
968 /* Remove the handle from the list */
970
971 /* Check if we have a destroy callback */
972 if (DestroyHandleProcedure)
973 {
974 /* FIXME: */
975 ASSERT(FALSE);
976 }
977
978 /* Free the handle table */
980}
VOID NTAPI ExRemoveHandleTable(IN PHANDLE_TABLE HandleTable)
Definition: handle.c:944
VOID NTAPI ExpFreeHandleTable(IN PHANDLE_TABLE HandleTable)
Definition: handle.c:202

Referenced by ObKillProcess(), and RtlpDestroyAtomHandleTable().

◆ ExDupHandleTable()

PHANDLE_TABLE NTAPI ExDupHandleTable ( IN PEPROCESS  Process,
IN PHANDLE_TABLE  HandleTable,
IN PEX_DUPLICATE_HANDLE_CALLBACK  DupHandleProcedure,
IN ULONG_PTR  Mask 
)

Definition at line 1072 of file handle.c.

1076{
1077 PHANDLE_TABLE NewTable;
1079 PHANDLE_TABLE_ENTRY HandleTableEntry, NewEntry;
1081 PAGED_CODE();
1082
1083 /* Allocate the duplicated copy */
1085 if (!NewTable) return NULL;
1086
1087 /* Loop each entry */
1088 while (NewTable->NextHandleNeedingPool <
1089 HandleTable->NextHandleNeedingPool)
1090 {
1091 /* Insert it into the duplicated copy */
1092 if (!ExpAllocateHandleTableEntrySlow(NewTable, FALSE))
1093 {
1094 /* Insert failed, free the new copy and return */
1095 ExpFreeHandleTable(NewTable);
1096 return NULL;
1097 }
1098 }
1099
1100 /* Setup the initial handle table data */
1101 NewTable->HandleCount = 0;
1102 NewTable->ExtraInfoPages = 0;
1103 NewTable->FirstFree = 0;
1104
1105 /* Setup the first handle value */
1106 Handle.Value = INDEX_TO_HANDLE_VALUE(1);
1107
1108 /* Enter a critical region and lookup the new entry */
1110 while ((NewEntry = ExpLookupHandleTableEntry(NewTable, Handle)))
1111 {
1112 /* Lookup the old entry */
1113 HandleTableEntry = ExpLookupHandleTableEntry(HandleTable, Handle);
1114
1115 /* Loop each entry */
1116 do
1117 {
1118 /* Check if it doesn't match the audit mask */
1119 if (!(HandleTableEntry->Value & Mask))
1120 {
1121 /* Free it since we won't use it */
1122 Failed = TRUE;
1123 }
1124 else
1125 {
1126 /* Lock the entry */
1127 if (!ExpLockHandleTableEntry(HandleTable, HandleTableEntry))
1128 {
1129 /* Free it since we can't lock it, so we won't use it */
1130 Failed = TRUE;
1131 }
1132 else
1133 {
1134 /* Copy the handle value */
1135 *NewEntry = *HandleTableEntry;
1136
1137 /* Call the duplicate callback */
1138 if (DupHandleProcedure(Process,
1140 HandleTableEntry,
1141 NewEntry))
1142 {
1143 /* Clear failure flag */
1144 Failed = FALSE;
1145
1146 /* Lock the entry, increase the handle count */
1148 NewTable->HandleCount++;
1149 }
1150 else
1151 {
1152 /* Duplication callback refused, fail */
1153 Failed = TRUE;
1154 }
1155 }
1156 }
1157
1158 /* Check if we failed earlier and need to free */
1159 if (Failed)
1160 {
1161 /* Free this entry */
1162 NewEntry->Object = NULL;
1163 NewEntry->NextFreeTableEntry = NewTable->FirstFree;
1164 NewTable->FirstFree = (ULONG)Handle.Value;
1165 }
1166
1167 /* Increase the handle value and move to the next entry */
1168 Handle.Value += INDEX_TO_HANDLE_VALUE(1);
1169 NewEntry++;
1170 HandleTableEntry++;
1172
1173 /* We're done, skip the last entry */
1174 Handle.Value += INDEX_TO_HANDLE_VALUE(1);
1175 }
1176
1177 /* Acquire the table lock and insert this new table into the list */
1181
1182 /* Leave the critical region we entered previously and return the table */
1184 return NewTable;
1185}
#define LOW_LEVEL_ENTRIES
Definition: ex.h:152
unsigned int Mask
Definition: fpcontrol.c:82
BOOLEAN NTAPI ExpAllocateHandleTableEntrySlow(IN PHANDLE_TABLE HandleTable, IN BOOLEAN DoInit)
Definition: handle.c:502
#define INDEX_TO_HANDLE_VALUE(x)
Definition: handle.c:21
@ Failed
Definition: arc.h:79
ULONG_PTR Value
Definition: extypes.h:602
LONG HandleCount
Definition: extypes.h:644
LONG ExtraInfoPages
Definition: extypes.h:635
ULONG NextHandleNeedingPool
Definition: extypes.h:645
LIST_ENTRY HandleTableList
Definition: extypes.h:627
uint32_t ULONG
Definition: typedefs.h:59

Referenced by ObInitProcess().

◆ ExEnumHandleTable()

BOOLEAN NTAPI ExEnumHandleTable ( IN PHANDLE_TABLE  HandleTable,
IN PEX_ENUM_HANDLE_CALLBACK  EnumHandleProcedure,
IN OUT PVOID  Context,
OUT PHANDLE EnumHandle  OPTIONAL 
)

Definition at line 1271 of file handle.c.

1275{
1277 PHANDLE_TABLE_ENTRY HandleTableEntry;
1279 PAGED_CODE();
1280
1281 /* Enter a critical region */
1283
1284 /* Set the initial value and loop the entries */
1285 Handle.Value = 0;
1286 while ((HandleTableEntry = ExpLookupHandleTableEntry(HandleTable, Handle)))
1287 {
1288 /* Validate the entry */
1289 if ((HandleTableEntry->Object) &&
1290 (HandleTableEntry->NextFreeTableEntry != -2))
1291 {
1292 /* Lock the entry */
1293 if (ExpLockHandleTableEntry(HandleTable, HandleTableEntry))
1294 {
1295 /* Notify the callback routine */
1296 Result = EnumHandleProcedure(HandleTableEntry,
1297 Handle.GenericHandleOverlay,
1298 Context);
1299
1300 /* Unlock it */
1301 ExUnlockHandleTableEntry(HandleTable, HandleTableEntry);
1302
1303 /* Was this the one looked for? */
1304 if (Result)
1305 {
1306 /* If so, return it if requested */
1307 if (EnumHandle) *EnumHandle = Handle.GenericHandleOverlay;
1308 break;
1309 }
1310 }
1311 }
1312
1313 /* Go to the next entry */
1314 Handle.Value += INDEX_TO_HANDLE_VALUE(1);
1315 }
1316
1317 /* Leave the critical region and return callback result */
1319 return Result;
1320}

Referenced by ObFindHandleForObject().

◆ ExMapHandleToPointer()

PHANDLE_TABLE_ENTRY NTAPI ExMapHandleToPointer ( IN PHANDLE_TABLE  HandleTable,
IN HANDLE  Handle 
)

Definition at line 1046 of file handle.c.

1048{
1049 EXHANDLE ExHandle;
1050 PHANDLE_TABLE_ENTRY HandleTableEntry;
1051 PAGED_CODE();
1052
1053 /* Set the handle value */
1054 ExHandle.GenericHandleOverlay = Handle;
1055
1056 /* Fail if we got an invalid index */
1057 if (!(ExHandle.Index & (LOW_LEVEL_ENTRIES - 1))) return NULL;
1058
1059 /* Do the lookup */
1060 HandleTableEntry = ExpLookupHandleTableEntry(HandleTable, ExHandle);
1061 if (!HandleTableEntry) return NULL;
1062
1063 /* Lock it */
1064 if (!ExpLockHandleTableEntry(HandleTable, HandleTableEntry)) return NULL;
1065
1066 /* Return the entry */
1067 return HandleTableEntry;
1068}
ULONG_PTR Index
Definition: ex.h:91

Referenced by NtWaitForMultipleObjects(), ObpCloseHandle(), ObpReferenceProcessObjectByHandle(), ObQueryObjectAuditingByHandle(), ObReferenceFileObjectForWrite(), ObReferenceObjectByHandle(), PsLookupProcessByProcessId(), PsLookupProcessThreadByCid(), PsLookupThreadByThreadId(), and RtlpGetAtomEntry().

◆ ExpAllocateHandleTable()

PHANDLE_TABLE NTAPI ExpAllocateHandleTable ( IN PEPROCESS Process  OPTIONAL,
IN BOOLEAN  NewTable 
)

Definition at line 331 of file handle.c.

333{
335 PHANDLE_TABLE_ENTRY HandleTableTable, HandleEntry;
336 ULONG i;
338 PAGED_CODE();
339
340 /* Allocate the table */
342 sizeof(HANDLE_TABLE),
344 if (!HandleTable) return NULL;
345
346 /* Check if we have a process */
347 if (Process)
348 {
349 /* Charge quota */
351 if (!NT_SUCCESS(Status))
352 {
354 return NULL;
355 }
356 }
357
358 /* Clear the table */
360
361 /* Now allocate the first level structures */
363 if (!HandleTableTable)
364 {
365 /* Failed, free the table */
367
368 /* Return the quota it was taking up */
369 if (Process)
370 {
372 }
373
374 return NULL;
375 }
376
377 /* Write the pointer to our first level structures */
378 HandleTable->TableCode = (ULONG_PTR)HandleTableTable;
379
380 /* Initialize the first entry */
381 HandleEntry = &HandleTableTable[0];
382 HandleEntry->NextFreeTableEntry = -2;
383 HandleEntry->Value = 0;
384
385 /* Check if this is a new table */
386 if (NewTable)
387 {
388 /* Go past the root entry */
389 HandleEntry++;
390
391 /* Loop every low level entry */
392 for (i = 1; i < (LOW_LEVEL_ENTRIES - 1); i++)
393 {
394 /* Set up the free data */
395 HandleEntry->Value = 0;
396 HandleEntry->NextFreeTableEntry = INDEX_TO_HANDLE_VALUE(i + 1);
397
398 /* Move to the next entry */
399 HandleEntry++;
400 }
401
402 /* Terminate the last entry */
403 HandleEntry->Value = 0;
404 HandleEntry->NextFreeTableEntry = 0;
405 HandleTable->FirstFree = INDEX_TO_HANDLE_VALUE(1);
406 }
407
408 /* Set the next handle needing pool after our allocated page from above */
409 HandleTable->NextHandleNeedingPool = INDEX_TO_HANDLE_VALUE(LOW_LEVEL_ENTRIES);
410
411 /* Setup the rest of the handle table data */
412 HandleTable->QuotaProcess = Process;
413 HandleTable->UniqueProcessId = PsGetCurrentProcess()->UniqueProcessId;
414 HandleTable->Flags = 0;
415
416 /* Loop all the handle table locks */
417 for (i = 0; i < 4; i++)
418 {
419 /* Initialize the handle table lock */
420 ExInitializePushLock(&HandleTable->HandleTableLock[i]);
421 }
422
423 /* Initialize the contention event lock and return the lock */
424 ExInitializePushLock(&HandleTable->HandleContentionEvent);
425 return HandleTable;
426}
LONG NTSTATUS
Definition: precomp.h:26
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define ULONG_PTR
Definition: config.h:101
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define PAGE_SIZE
Definition: env_spec_w32.h:49
#define PagedPool
Definition: env_spec_w32.h:308
#define ExInitializePushLock
Definition: ex.h:1013
Status
Definition: gdiplustypes.h:25
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1109
PVOID NTAPI ExpAllocateTablePagedPoolNoZero(IN PEPROCESS Process OPTIONAL, IN SIZE_T Size)
Definition: handle.c:139
VOID NTAPI PsReturnProcessPagedPoolQuota(_In_ PEPROCESS Process, _In_ SIZE_T Amount)
Returns the paged pool quota that the process was taking up.
Definition: quota.c:965
NTSTATUS NTAPI PsChargeProcessPagedPoolQuota(_In_ PEPROCESS Process, _In_ SIZE_T Amount)
Charges the paged pool quota of a given process.
Definition: quota.c:839
#define TAG_OBJECT_TABLE
Definition: tag.h:26
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define PsGetCurrentProcess
Definition: psfuncs.h:17

Referenced by ExCreateHandleTable(), and ExDupHandleTable().

◆ ExpAllocateHandleTableEntry()

PHANDLE_TABLE_ENTRY NTAPI ExpAllocateHandleTableEntry ( IN PHANDLE_TABLE  HandleTable,
OUT PEXHANDLE  NewHandle 
)

Definition at line 683 of file handle.c.

685{
686 ULONG OldValue, NewValue, NewValue1;
688 EXHANDLE Handle, OldHandle;
690 ULONG i;
691
692 /* Start allocation loop */
693 for (;;)
694 {
695 /* Get the current link */
696 OldValue = HandleTable->FirstFree;
697 while (!OldValue)
698 {
699 /* No free entries remain, lock the handle table */
701 ExAcquirePushLockExclusive(&HandleTable->HandleTableLock[0]);
702
703 /* Check the value again */
704 OldValue = HandleTable->FirstFree;
705 if (OldValue)
706 {
707 /* Another thread has already created a new level, bail out */
708 ExReleasePushLockExclusive(&HandleTable->HandleTableLock[0]);
710 break;
711 }
712
713 /* Now move any free handles */
715 if (OldValue)
716 {
717 /* Another thread has already moved them, bail out */
718 ExReleasePushLockExclusive(&HandleTable->HandleTableLock[0]);
720 break;
721 }
722
723 /* We're the first one through, so do the actual allocation */
725
726 /* Unlock the table and get the value now */
727 ExReleasePushLockExclusive(&HandleTable->HandleTableLock[0]);
729 OldValue = HandleTable->FirstFree;
730
731 /* Check if allocation failed */
732 if (!Result)
733 {
734 /* Check if nobody else went through here */
735 if (!OldValue)
736 {
737 /* We're still the only thread around, so fail */
738 NewHandle->GenericHandleOverlay = NULL;
739 return NULL;
740 }
741 }
742 }
743
744 /* We made it, write the current value */
745 Handle.Value = (OldValue & FREE_HANDLE_MASK);
746
747 /* Lookup the entry for this handle */
749
750 /* Get an available lock and acquire it */
751 OldHandle.Value = OldValue;
752 i = OldHandle.Index % 4;
754 ExAcquirePushLockShared(&HandleTable->HandleTableLock[i]);
755
756 /* Check if the value changed after acquiring the lock */
757 if (OldValue != *(volatile ULONG*)&HandleTable->FirstFree)
758 {
759 /* It did, so try again */
760 ExReleasePushLockShared(&HandleTable->HandleTableLock[i]);
762 continue;
763 }
764
765 /* Now get the next value and do the compare */
766 NewValue = *(volatile ULONG*)&Entry->NextFreeTableEntry;
767 NewValue1 = InterlockedCompareExchange((PLONG) &HandleTable->FirstFree,
768 NewValue,
769 OldValue);
770
771 /* The change was done, so release the lock */
772 ExReleasePushLockShared(&HandleTable->HandleTableLock[i]);
774
775 /* Check if the compare was successful */
776 if (NewValue1 == OldValue)
777 {
778 /* Make sure that the new handle is in range, and break out */
779 ASSERT((NewValue & FREE_HANDLE_MASK) <
780 HandleTable->NextHandleNeedingPool);
781 break;
782 }
783 else
784 {
785 /* The compare failed, make sure we expected it */
786 ASSERT((NewValue1 & FREE_HANDLE_MASK) !=
787 (OldValue & FREE_HANDLE_MASK));
788 }
789 }
790
791 /* Increase the number of handles */
792 InterlockedIncrement(&HandleTable->HandleCount);
793
794 /* Return the handle and the entry */
795 *NewHandle = Handle;
796 return Entry;
797}
#define InterlockedIncrement
Definition: armddk.h:53
#define FREE_HANDLE_MASK
Definition: ex.h:147
FORCEINLINE VOID ExAcquirePushLockShared(PEX_PUSH_LOCK PushLock)
Definition: ex.h:1105
FORCEINLINE VOID ExReleasePushLockShared(PEX_PUSH_LOCK PushLock)
Definition: ex.h:1213
#define InterlockedCompareExchange
Definition: interlocked.h:104
ULONG NTAPI ExpMoveFreeHandles(IN PHANDLE_TABLE HandleTable)
Definition: handle.c:648
base of all file and directory entries
Definition: entries.h:83
int32_t * PLONG
Definition: typedefs.h:58
ULONG_PTR Value
Definition: ex.h:103

Referenced by ExCreateHandle().

◆ ExpAllocateHandleTableEntrySlow()

BOOLEAN NTAPI ExpAllocateHandleTableEntrySlow ( IN PHANDLE_TABLE  HandleTable,
IN BOOLEAN  DoInit 
)

Definition at line 502 of file handle.c.

504{
505 ULONG i, j, Index;
506 PHANDLE_TABLE_ENTRY Low = NULL, *Mid, **High, *SecondLevel, **ThirdLevel;
507 ULONG NewFree, FirstFree;
508 PVOID Value;
509 ULONG_PTR TableCode = HandleTable->TableCode;
510 ULONG_PTR TableBase = TableCode & ~3;
511 ULONG TableLevel = (ULONG)(TableCode & 3);
512 PAGED_CODE();
513
514 /* Check how many levels we already have */
515 if (TableLevel == 0)
516 {
517 /* Allocate a mid level, since we only have a low level */
519 if (!Mid) return FALSE;
520
521 /* Link up the tables */
522 Mid[1] = Mid[0];
523 Mid[0] = (PVOID)TableBase;
524
525 /* Write the new level and attempt to change the table code */
526 TableBase = ((ULONG_PTR)Mid) | 1;
527 Value = InterlockedExchangePointer((PVOID*)&HandleTable->TableCode, (PVOID)TableBase);
528 }
529 else if (TableLevel == 1)
530 {
531 /* Setup the 2nd level table */
532 SecondLevel = (PVOID)TableBase;
533
534 /* Get if the next index can fit in the table */
535 i = HandleTable->NextHandleNeedingPool /
537 if (i < MID_LEVEL_ENTRIES)
538 {
539 /* We need to allocate a new table */
541 if (!Low) return FALSE;
542
543 /* Update the table */
544 Value = InterlockedExchangePointer((PVOID*)&SecondLevel[i], Low);
545 ASSERT(Value == NULL);
546 }
547 else
548 {
549 /* We need a new high level table */
552 if (!High) return FALSE;
553
554 /* Allocate a new mid level table as well */
556 if (!Mid)
557 {
558 /* We failed, free the high level table as well */
560 High,
562 return FALSE;
563 }
564
565 /* Link up the tables */
566 High[0] = (PVOID)TableBase;
567 High[1] = Mid;
568
569 /* Write the new table and change the table code */
570 TableBase = ((ULONG_PTR)High) | 2;
572 (PVOID)TableBase);
573 }
574 }
575 else if (TableLevel == 2)
576 {
577 /* Setup the 3rd level table */
578 ThirdLevel = (PVOID)TableBase;
579
580 /* Get the index and check if it can fit */
581 i = HandleTable->NextHandleNeedingPool / INDEX_TO_HANDLE_VALUE(MAX_MID_INDEX);
582 if (i >= HIGH_LEVEL_ENTRIES) return FALSE;
583
584 /* Check if there's no mid-level table */
585 if (!ThirdLevel[i])
586 {
587 /* Allocate a new mid level table */
589 if (!Mid) return FALSE;
590
591 /* Update the table pointer */
592 Value = InterlockedExchangePointer((PVOID*)&ThirdLevel[i], Mid);
593 ASSERT(Value == NULL);
594 }
595 else
596 {
597 /* We have one, check at which index we should insert our entry */
598 Index = (HandleTable->NextHandleNeedingPool / INDEX_TO_HANDLE_VALUE(1)) -
601
602 /* Allocate a new low level */
604 if (!Low) return FALSE;
605
606 /* Update the table pointer */
607 Value = InterlockedExchangePointer((PVOID*)&ThirdLevel[i][j], Low);
608 ASSERT(Value == NULL);
609 }
610 }
611 else
612 {
613 /* Something is really broken */
614 ASSERT(FALSE);
615 }
616
617 /* Update the index of the next handle */
618 Index = InterlockedExchangeAdd((PLONG) &HandleTable->NextHandleNeedingPool,
620
621 /* Check if need to initialize the table */
622 if (DoInit)
623 {
624 /* Create a new index number */
626
627 /* Start free index change loop */
628 for (;;)
629 {
630 /* Setup the first free index */
631 FirstFree = HandleTable->FirstFree;
632 Low[LOW_LEVEL_ENTRIES - 1].NextFreeTableEntry = FirstFree;
633
634 /* Change the index */
635 NewFree = InterlockedCompareExchange((PLONG) &HandleTable->FirstFree,
636 Index,
637 FirstFree);
638 if (NewFree == FirstFree) break;
639 }
640 }
641
642 /* All done */
643 return TRUE;
644}
#define MID_LEVEL_ENTRIES
Definition: ex.h:153
#define HIGH_LEVEL_ENTRIES
Definition: ex.h:154
#define MAX_MID_INDEX
Definition: ex.h:160
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
#define InterlockedExchangeAdd
Definition: interlocked.h:181
PVOID NTAPI ExpAllocateTablePagedPool(IN PEPROCESS Process OPTIONAL, IN SIZE_T Size)
Definition: handle.c:107
VOID NTAPI ExpFreeTablePagedPool(IN PEPROCESS Process OPTIONAL, IN PVOID Buffer, IN SIZE_T Size)
Definition: handle.c:168
PHANDLE_TABLE_ENTRY NTAPI ExpAllocateLowLevelTable(IN PHANDLE_TABLE HandleTable, IN BOOLEAN DoInit)
Definition: handle.c:430
#define SizeOfHandle(x)
Definition: handle.c:20
PHANDLE_TABLE_ENTRY *NTAPI ExpAllocateMidLevelTable(IN PHANDLE_TABLE HandleTable, IN BOOLEAN DoInit, OUT PHANDLE_TABLE_ENTRY *LowTableEntry)
Definition: handle.c:475
@ High
Definition: strmini.h:378
@ Low
Definition: strmini.h:380
void * PVOID
Definition: typedefs.h:50
_In_ WDFCOLLECTION _In_ ULONG Index
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING _Out_opt_ PUSHORT _Inout_opt_ PUNICODE_STRING Value
Definition: wdfregistry.h:413

Referenced by ExDupHandleTable(), and ExpAllocateHandleTableEntry().

◆ ExpAllocateLowLevelTable()

PHANDLE_TABLE_ENTRY NTAPI ExpAllocateLowLevelTable ( IN PHANDLE_TABLE  HandleTable,
IN BOOLEAN  DoInit 
)

Definition at line 430 of file handle.c.

432{
433 ULONG i, Base;
434 PHANDLE_TABLE_ENTRY Low, HandleEntry;
435
436 /* Allocate the low level table */
438 PAGE_SIZE);
439 if (!Low) return NULL;
440
441 /* Setup the initial entry */
442 HandleEntry = &Low[0];
443 HandleEntry->NextFreeTableEntry = -2;
444 HandleEntry->Value = 0;
445
446 /* Check if we're initializing */
447 if (DoInit)
448 {
449 /* Go to the next entry and the base entry */
450 HandleEntry++;
451 Base = HandleTable->NextHandleNeedingPool + INDEX_TO_HANDLE_VALUE(2);
452
453 /* Loop each entry */
454 for (i = Base;
457 {
458 /* Free this entry and move on to the next one */
459 HandleEntry->NextFreeTableEntry = i;
460 HandleEntry->Value = 0;
461 HandleEntry++;
462 }
463
464 /* Terminate the last entry */
465 HandleEntry->NextFreeTableEntry = 0;
466 HandleEntry->Value = 0;
467 }
468
469 /* Return the low level table */
470 return Low;
471}
_In_opt_ ULONG Base
Definition: rtlfuncs.h:2439

Referenced by ExpAllocateHandleTableEntrySlow(), and ExpAllocateMidLevelTable().

◆ ExpAllocateMidLevelTable()

PHANDLE_TABLE_ENTRY *NTAPI ExpAllocateMidLevelTable ( IN PHANDLE_TABLE  HandleTable,
IN BOOLEAN  DoInit,
OUT PHANDLE_TABLE_ENTRY LowTableEntry 
)

Definition at line 475 of file handle.c.

478{
480
481 /* Allocate the mid level table */
482 Mid = ExpAllocateTablePagedPool(HandleTable->QuotaProcess, PAGE_SIZE);
483 if (!Mid) return NULL;
484
485 /* Allocate a new low level for it */
487 if (!Low)
488 {
489 /* We failed, free the mid table */
490 ExpFreeTablePagedPool(HandleTable->QuotaProcess, Mid, PAGE_SIZE);
491 return NULL;
492 }
493
494 /* Link the tables and return the pointer */
495 Mid[0] = Low;
496 *LowTableEntry = Low;
497 return Mid;
498}

Referenced by ExpAllocateHandleTableEntrySlow().

◆ ExpAllocateTablePagedPool()

PVOID NTAPI ExpAllocateTablePagedPool ( IN PEPROCESS Process  OPTIONAL,
IN SIZE_T  Size 
)

Definition at line 107 of file handle.c.

109{
112
113 /* Do the allocation */
115 if (Buffer)
116 {
117 /* Clear the memory */
119
120 /* Check if we have a process to charge quota */
121 if (Process)
122 {
123 /* Charge quota */
125 if (!NT_SUCCESS(Status))
126 {
128 return NULL;
129 }
130 }
131 }
132
133 /* Return the allocated memory */
134 return Buffer;
135}
Definition: bufpool.h:45
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_DEVICE_PROPERTY_DATA _In_ DEVPROPTYPE _In_ ULONG Size
Definition: wdfdevice.h:4533

Referenced by ExpAllocateHandleTableEntrySlow(), and ExpAllocateMidLevelTable().

◆ ExpAllocateTablePagedPoolNoZero()

PVOID NTAPI ExpAllocateTablePagedPoolNoZero ( IN PEPROCESS Process  OPTIONAL,
IN SIZE_T  Size 
)

Definition at line 139 of file handle.c.

141{
144
145 /* Do the allocation */
147 if (Buffer)
148 {
149 /* Check if we have a process to charge quota */
150 if (Process)
151 {
152 /* Charge quota */
154 if (!NT_SUCCESS(Status))
155 {
157 return NULL;
158 }
159 }
160 }
161
162 /* Return the allocated memory */
163 return Buffer;
164}

Referenced by ExpAllocateHandleTable(), and ExpAllocateLowLevelTable().

◆ ExpBlockOnLockedHandleEntry()

VOID NTAPI ExpBlockOnLockedHandleEntry ( IN PHANDLE_TABLE  HandleTable,
IN PHANDLE_TABLE_ENTRY  HandleTableEntry 
)

Definition at line 858 of file handle.c.

860{
861 LONG_PTR OldValue;
862 EX_PUSH_LOCK_WAIT_BLOCK WaitBlock;
863
864 /* Block on the pushlock */
865 ExBlockPushLock(&HandleTable->HandleContentionEvent, &WaitBlock);
866
867 /* Get the current value and check if it's been unlocked */
868 OldValue = HandleTableEntry->Value;
869 if (!(OldValue) || (OldValue & EXHANDLE_TABLE_ENTRY_LOCK_BIT))
870 {
871 /* Unblock the pushlock and return */
872 ExfUnblockPushLock(&HandleTable->HandleContentionEvent, &WaitBlock);
873 }
874 else
875 {
876 /* Wait for it to be unblocked */
877 ExWaitForUnblockPushLock(&HandleTable->HandleContentionEvent,
878 &WaitBlock);
879 }
880}
__int3264 LONG_PTR
Definition: mstsclib_h.h:276
EX_PUSH_LOCK_WAIT_BLOCK
Definition: extypes.h:501
VOID FASTCALL ExWaitForUnblockPushLock(IN PEX_PUSH_LOCK PushLock, IN PVOID WaitBlock)
Definition: pushlock.c:395
VOID FASTCALL ExBlockPushLock(PEX_PUSH_LOCK PushLock, PVOID pWaitBlock)
Definition: pushlock.c:420

Referenced by ExpLockHandleTableEntry().

◆ ExpFreeHandleTable()

VOID NTAPI ExpFreeHandleTable ( IN PHANDLE_TABLE  HandleTable)

Definition at line 202 of file handle.c.

203{
204 PEPROCESS Process = HandleTable->QuotaProcess;
205 ULONG i, j;
206 ULONG_PTR TableCode = HandleTable->TableCode;
207 ULONG_PTR TableBase = TableCode & ~3;
208 ULONG TableLevel = (ULONG)(TableCode & 3);
209 PHANDLE_TABLE_ENTRY Level1, *Level2, **Level3;
210 PAGED_CODE();
211
212 /* Check which level we're at */
213 if (TableLevel == 0)
214 {
215 /* Select the first level table base and just free it */
216 Level1 = (PVOID)TableBase;
218 }
219 else if (TableLevel == 1)
220 {
221 /* Select the second level table base */
222 Level2 = (PVOID)TableBase;
223
224 /* Loop each mid level entry */
225 for (i = 0; i < MID_LEVEL_ENTRIES; i++)
226 {
227 /* Leave if we've reached the last entry */
228 if (!Level2[i]) break;
229
230 /* Free the second level table */
232 }
233
234 /* Free the second level table */
236 }
237 else
238 {
239 /* Select the third level table base */
240 Level3 = (PVOID)TableBase;
241
242 /* Loop each high level entry */
243 for (i = 0; i < HIGH_LEVEL_ENTRIES; i++)
244 {
245 /* Leave if we've reached the last entry */
246 if (!Level3[i]) break;
247
248 /* Loop each mid level entry */
249 for (j = 0; j < MID_LEVEL_ENTRIES; j++)
250 {
251 /* Leave if we've reached the last entry */
252 if (!Level3[i][j]) break;
253
254 /* Free the second level table */
255 ExpFreeLowLevelTable(Process, Level3[i][j]);
256 }
257
258 /* Free the third level table entry */
260 }
261
262 /* Free the third level table */
264 Level3,
266 }
267
268 /* Free the actual table and check if we need to release quota */
270 if (Process)
271 {
272 /* Release the quota it was taking up */
274 }
275}
VOID NTAPI ExpFreeLowLevelTable(IN PEPROCESS Process, IN PHANDLE_TABLE_ENTRY TableEntry)
Definition: handle.c:183

Referenced by ExDestroyHandleTable(), and ExDupHandleTable().

◆ ExpFreeHandleTableEntry()

VOID NTAPI ExpFreeHandleTableEntry ( IN PHANDLE_TABLE  HandleTable,
IN EXHANDLE  Handle,
IN PHANDLE_TABLE_ENTRY  HandleTableEntry 
)

Definition at line 279 of file handle.c.

282{
283 ULONG OldValue, *Free;
284 ULONG LockIndex;
285 PAGED_CODE();
286
287 /* Sanity checks */
288 ASSERT(HandleTableEntry->Object == NULL);
289 ASSERT(HandleTableEntry == ExpLookupHandleTableEntry(HandleTable, Handle));
290
291 /* Decrement the handle count */
292 InterlockedDecrement(&HandleTable->HandleCount);
293
294 /* Mark the handle as free */
295 Handle.TagBits = 0;
296
297 /* Check if we're FIFO */
298 if (!HandleTable->StrictFIFO)
299 {
300 /* Select a lock index */
301 LockIndex = Handle.Index % 4;
302
303 /* Select which entry to use */
304 Free = (HandleTable->HandleTableLock[LockIndex].Locked) ?
305 &HandleTable->FirstFree : &HandleTable->LastFree;
306 }
307 else
308 {
309 /* No need to worry about locking, take the last entry */
310 Free = &HandleTable->LastFree;
311 }
312
313 /* Start value change loop */
314 for (;;)
315 {
316 /* Get the current value and write */
317 OldValue = *Free;
318 HandleTableEntry->NextFreeTableEntry = OldValue;
319 if (InterlockedCompareExchange((PLONG)Free, Handle.AsULONG, OldValue) == OldValue)
320 {
321 /* Break out, we're done. Make sure the handle value makes sense */
322 ASSERT((OldValue & FREE_HANDLE_MASK) <
323 HandleTable->NextHandleNeedingPool);
324 break;
325 }
326 }
327}
#define InterlockedDecrement
Definition: armddk.h:52
_In_opt_ PALLOCATE_FUNCTION _In_opt_ PFREE_FUNCTION Free
Definition: exfuncs.h:815

Referenced by ExDestroyHandle().

◆ ExpFreeLowLevelTable()

VOID NTAPI ExpFreeLowLevelTable ( IN PEPROCESS  Process,
IN PHANDLE_TABLE_ENTRY  TableEntry 
)

Definition at line 183 of file handle.c.

185{
186 /* Check if we have an entry */
187 if (TableEntry[0].Object)
188 {
189 /* Free the entry */
194 }
195
196 /* Free the table */
198}
Definition: extypes.h:591
_Must_inspect_result_ typedef _In_ ULONG TableEntry
Definition: iotypes.h:4303

Referenced by ExpFreeHandleTable().

◆ ExpFreeTablePagedPool()

VOID NTAPI ExpFreeTablePagedPool ( IN PEPROCESS Process  OPTIONAL,
IN PVOID  Buffer,
IN SIZE_T  Size 
)

Definition at line 168 of file handle.c.

171{
172 /* Free the buffer */
174 if (Process)
175 {
176 /* Release quota */
178 }
179}

Referenced by ExpAllocateHandleTableEntrySlow(), ExpAllocateMidLevelTable(), ExpFreeHandleTable(), and ExpFreeLowLevelTable().

◆ ExpInitializeHandleTables()

VOID NTAPI ExpInitializeHandleTables ( VOID  )

Definition at line 34 of file handle.c.

35{
36 /* Initialize the list of handle tables and the lock */
39}
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944

Referenced by ExpInitializeExecutive().

◆ ExpLockHandleTableEntry()

BOOLEAN NTAPI ExpLockHandleTableEntry ( IN PHANDLE_TABLE  HandleTable,
IN PHANDLE_TABLE_ENTRY  HandleTableEntry 
)

Definition at line 884 of file handle.c.

886{
887 LONG_PTR NewValue, OldValue;
888
889 /* Sanity check */
890 ASSERT((KeGetCurrentThread()->CombinedApcDisable != 0) ||
892
893 /* Start lock loop */
894 for (;;)
895 {
896 /* Get the current value and check if it's locked */
897 OldValue = *(volatile LONG_PTR *)&HandleTableEntry->Object;
899 {
900 /* It's not locked, remove the lock bit to lock it */
901 NewValue = OldValue & ~EXHANDLE_TABLE_ENTRY_LOCK_BIT;
902 if (InterlockedCompareExchangePointer(&HandleTableEntry->Object,
903 (PVOID)NewValue,
904 (PVOID)OldValue) == (PVOID)OldValue)
905 {
906 /* We locked it, get out */
907 return TRUE;
908 }
909 }
910 else
911 {
912 /* We couldn't lock it, bail out if it's been freed */
913 if (!OldValue) return FALSE;
914 }
915
916 /* It's locked, wait for it to be unlocked */
917 ExpBlockOnLockedHandleEntry(HandleTable, HandleTableEntry);
918 }
919}
#define APC_LEVEL
Definition: env_spec_w32.h:695
#define KeGetCurrentIrql()
Definition: env_spec_w32.h:706
#define KeGetCurrentThread
Definition: hal.h:55
#define InterlockedCompareExchangePointer
Definition: interlocked.h:129
if(dx< 0)
Definition: linetemp.h:194
VOID NTAPI ExpBlockOnLockedHandleEntry(IN PHANDLE_TABLE HandleTable, IN PHANDLE_TABLE_ENTRY HandleTableEntry)
Definition: handle.c:858

Referenced by ExChangeHandle(), ExDestroyHandle(), ExDupHandleTable(), ExEnumHandleTable(), ExMapHandleToPointer(), ExSweepHandleTable(), and QSI_DEF().

◆ ExpLookupHandleTableEntry()

PHANDLE_TABLE_ENTRY NTAPI ExpLookupHandleTableEntry ( IN PHANDLE_TABLE  HandleTable,
IN EXHANDLE  Handle 
)

Definition at line 43 of file handle.c.

45{
46 ULONG TableLevel;
47 ULONG_PTR TableBase;
48 PHANDLE_TABLE_ENTRY HandleArray, Entry;
49 PVOID *PointerArray;
50
51 /* Clear the tag bits */
52 Handle.TagBits = 0;
53
54 /* Check if the handle is in the allocated range */
55 if (Handle.Value >= HandleTable->NextHandleNeedingPool)
56 {
57 return NULL;
58 }
59
60 /* Get the table code */
61 TableBase = HandleTable->TableCode;
62
63 /* Extract the table level and actual table base */
64 TableLevel = (ULONG)(TableBase & 3);
65 TableBase &= ~3;
66
67 PointerArray = (PVOID*)TableBase;
68 HandleArray = (PHANDLE_TABLE_ENTRY)TableBase;
69
70 /* Check what level we're running at */
71 switch (TableLevel)
72 {
73 case 2:
74
75 /* Get the mid level pointer array */
76 PointerArray = PointerArray[Handle.HighIndex];
77 ASSERT(PointerArray != NULL);
78
79 /* Fall through */
80 case 1:
81
82 /* Get the handle array */
83 HandleArray = PointerArray[Handle.MidIndex];
84 ASSERT(HandleArray != NULL);
85
86 /* Fall through */
87 case 0:
88
89 /* Get the entry using the low index */
90 Entry = &HandleArray[Handle.LowIndex];
91
92 /* All done */
93 break;
94
95 default:
96
98 Entry = NULL;
99 }
100
101 /* Return the handle entry */
102 return Entry;
103}
struct _HANDLE_TABLE_ENTRY * PHANDLE_TABLE_ENTRY

Referenced by ExChangeHandle(), ExDestroyHandle(), ExDupHandleTable(), ExEnumHandleTable(), ExMapHandleToPointer(), ExpAllocateHandleTableEntry(), ExpFreeHandleTableEntry(), ExSweepHandleTable(), and QSI_DEF().

◆ ExpMoveFreeHandles()

ULONG NTAPI ExpMoveFreeHandles ( IN PHANDLE_TABLE  HandleTable)

Definition at line 648 of file handle.c.

649{
650 ULONG LastFree, i;
651
652 /* Clear the last free index */
653 LastFree = InterlockedExchange((PLONG) &HandleTable->LastFree, 0);
654
655 /* Check if we had no index */
656 if (!LastFree) return LastFree;
657
658 /* Acquire the locks we need */
659 for (i = 1; i < 4; i++)
660 {
661 /* Acquire this lock exclusively */
662 ExWaitOnPushLock(&HandleTable->HandleTableLock[i]);
663 }
664
665 /* Check if we're not strict FIFO */
666 if (!HandleTable->StrictFIFO)
667 {
668 /* Update the first free index */
669 if (!InterlockedCompareExchange((PLONG) &HandleTable->FirstFree, LastFree, 0))
670 {
671 /* We're done, exit */
672 return LastFree;
673 }
674 }
675
676 /* We are strict FIFO, we need to reverse the entries */
677 ASSERT(FALSE);
678 return LastFree;
679}
#define InterlockedExchange
Definition: armddk.h:54
FORCEINLINE VOID ExWaitOnPushLock(PEX_PUSH_LOCK PushLock)
Definition: ex.h:1178

Referenced by ExpAllocateHandleTableEntry().

◆ ExRemoveHandleTable()

VOID NTAPI ExRemoveHandleTable ( IN PHANDLE_TABLE  HandleTable)

Definition at line 944 of file handle.c.

945{
946 PAGED_CODE();
947
948 /* Acquire the table lock */
951
952 /* Remove the table and reset the list */
953 RemoveEntryList(&HandleTable->HandleTableList);
954 InitializeListHead(&HandleTable->HandleTableList);
955
956 /* Release the lock */
959}
#define RemoveEntryList(Entry)
Definition: env_spec_w32.h:986

Referenced by ExDestroyHandleTable().

◆ ExSweepHandleTable()

VOID NTAPI ExSweepHandleTable ( IN PHANDLE_TABLE  HandleTable,
IN PEX_SWEEP_HANDLE_CALLBACK  EnumHandleProcedure,
IN PVOID  Context 
)

Definition at line 1232 of file handle.c.

1235{
1237 PHANDLE_TABLE_ENTRY HandleTableEntry;
1238 PAGED_CODE();
1239
1240 /* Set the initial value and loop the entries */
1241 Handle.Value = INDEX_TO_HANDLE_VALUE(1);
1242 while ((HandleTableEntry = ExpLookupHandleTableEntry(HandleTable, Handle)))
1243 {
1244 /* Loop each handle */
1245 do
1246 {
1247 /* Lock the entry */
1248 if (ExpLockHandleTableEntry(HandleTable, HandleTableEntry))
1249 {
1250 /* Notify the callback routine */
1251 EnumHandleProcedure(HandleTableEntry,
1252 Handle.GenericHandleOverlay,
1253 Context);
1254 }
1255
1256 /* Go to the next handle and entry */
1257 Handle.Value += INDEX_TO_HANDLE_VALUE(1);
1258 HandleTableEntry++;
1260
1261 /* Skip past the last entry */
1262 Handle.Value += INDEX_TO_HANDLE_VALUE(1);
1263 }
1264}

Referenced by ObClearProcessHandleTable(), ObKillProcess(), and RtlpDestroyAtomHandleTable().

◆ ExUnlockHandleTableEntry()

VOID NTAPI ExUnlockHandleTableEntry ( IN PHANDLE_TABLE  HandleTable,
IN PHANDLE_TABLE_ENTRY  HandleTableEntry 
)

Definition at line 923 of file handle.c.

925{
926 LONG_PTR OldValue;
927 PAGED_CODE();
928
929 /* Sanity check */
930 ASSERT((KeGetCurrentThread()->CombinedApcDisable != 0) ||
932
933 /* Set the lock bit and make sure it wasn't earlier */
934 OldValue = InterlockedOr((PLONG) &HandleTableEntry->Value,
936 ASSERT((OldValue & EXHANDLE_TABLE_ENTRY_LOCK_BIT) == 0);
937
938 /* Unblock any waiters */
939 ExfUnblockPushLock(&HandleTable->HandleContentionEvent, NULL);
940}
#define InterlockedOr
Definition: interlocked.h:224

Referenced by ExChangeHandle(), ExCreateHandle(), ExEnumHandleTable(), NtWaitForMultipleObjects(), ObpCloseHandleTableEntry(), ObpDuplicateHandleCallback(), ObpReferenceProcessObjectByHandle(), ObQueryObjectAuditingByHandle(), ObReferenceFileObjectForWrite(), ObReferenceObjectByHandle(), PsLookupProcessByProcessId(), PsLookupProcessThreadByCid(), PsLookupThreadByThreadId(), QSI_DEF(), and RtlpGetAtomEntry().

Variable Documentation

◆ HandleTableListHead

LIST_ENTRY HandleTableListHead

Definition at line 18 of file handle.c.

Referenced by ExCreateHandleTable(), ExDupHandleTable(), ExpInitializeHandleTables(), and QSI_DEF().

◆ HandleTableListLock

EX_PUSH_LOCK HandleTableListLock