1 /* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: ReactOS system libraries 4 * PURPOSE: Handle table 5 * FILE: lib/rtl/handle.c 6 * PROGRAMMER: Eric Kohl 7 */ 8 9 /* INCLUDES *****************************************************************/ 10 11 #include <rtl.h> 12 13 #define NDEBUG 14 #include <debug.h> 15 16 /* GLOBALS ******************************************************************/ 17 18 VOID 19 NTAPI 20 RtlInitializeHandleTable( 21 ULONG TableSize, 22 ULONG HandleSize, 23 PRTL_HANDLE_TABLE HandleTable) 24 { 25 /* Initialize handle table */ 26 memset(HandleTable, 0, sizeof(RTL_HANDLE_TABLE)); 27 HandleTable->MaximumNumberOfHandles = TableSize; 28 HandleTable->SizeOfHandleTableEntry = HandleSize; 29 } 30 31 32 /* 33 * @implemented 34 */ 35 VOID 36 NTAPI 37 RtlDestroyHandleTable( 38 PRTL_HANDLE_TABLE HandleTable) 39 { 40 PVOID ArrayPointer; 41 SIZE_T ArraySize = 0; 42 43 /* free handle array */ 44 if (HandleTable->CommittedHandles) 45 { 46 ArrayPointer = (PVOID)HandleTable->CommittedHandles; 47 NtFreeVirtualMemory(NtCurrentProcess(), 48 &ArrayPointer, 49 &ArraySize, 50 MEM_RELEASE); 51 } 52 } 53 54 55 /* 56 * @implemented 57 */ 58 PRTL_HANDLE_TABLE_ENTRY 59 NTAPI 60 RtlAllocateHandle( 61 PRTL_HANDLE_TABLE HandleTable, 62 PULONG Index) 63 { 64 PRTL_HANDLE_TABLE_ENTRY CurrentEntry, NextEntry; 65 NTSTATUS Status; 66 PRTL_HANDLE_TABLE_ENTRY HandleEntry; 67 PVOID ArrayPointer; 68 SIZE_T ArraySize; 69 ULONG i, NumberOfEntries; 70 71 /* Check if we are out of free handles entries */ 72 if (HandleTable->FreeHandles == NULL) 73 { 74 /* Check if we don't have uncomitted handle entries yet */ 75 if (HandleTable->UnCommittedHandles == NULL) 76 { 77 /* Use the maximum number of handle entries */ 78 ArraySize = HandleTable->SizeOfHandleTableEntry * HandleTable->MaximumNumberOfHandles; 79 ArrayPointer = NULL; 80 81 /* Reserve memory */ 82 Status = ZwAllocateVirtualMemory(NtCurrentProcess(), 83 &ArrayPointer, 84 0, 85 &ArraySize, 86 MEM_RESERVE, 87 PAGE_READWRITE); 88 if (!NT_SUCCESS(Status)) 89 return NULL; 90 91 /* Update handle array pointers */ 92 HandleTable->UnCommittedHandles = (PRTL_HANDLE_TABLE_ENTRY)ArrayPointer; 93 HandleTable->MaxReservedHandles = (PRTL_HANDLE_TABLE_ENTRY)((ULONG_PTR)ArrayPointer + ArraySize); 94 } 95 96 /* Commit one reserved handle entry page */ 97 ArraySize = PAGE_SIZE; 98 ArrayPointer = HandleTable->UnCommittedHandles; 99 Status = ZwAllocateVirtualMemory(NtCurrentProcess(), 100 &ArrayPointer, 101 0, 102 &ArraySize, 103 MEM_COMMIT, 104 PAGE_READWRITE); 105 if (!NT_SUCCESS(Status)) 106 return NULL; 107 108 /* Update handle array pointers */ 109 HandleTable->FreeHandles = (PRTL_HANDLE_TABLE_ENTRY)ArrayPointer; 110 HandleTable->CommittedHandles = (PRTL_HANDLE_TABLE_ENTRY)ArrayPointer; 111 HandleTable->UnCommittedHandles = (PRTL_HANDLE_TABLE_ENTRY)((ULONG_PTR)ArrayPointer + ArraySize); 112 113 /* Calculate the number of entries we can store in the array */ 114 NumberOfEntries = ArraySize / HandleTable->SizeOfHandleTableEntry; 115 116 /* Loop all entries, except the last one */ 117 CurrentEntry = HandleTable->FreeHandles; 118 for (i = 0; i < NumberOfEntries - 1; i++) 119 { 120 /* Calculate the address of the next handle entry */ 121 NextEntry = (PRTL_HANDLE_TABLE_ENTRY)((ULONG_PTR)CurrentEntry + 122 HandleTable->SizeOfHandleTableEntry); 123 124 /* Link the next entry */ 125 CurrentEntry->NextFree = NextEntry; 126 127 /* Continue with the next entry */ 128 CurrentEntry = NextEntry; 129 } 130 131 /* CurrentEntry now points to the last entry, terminate the list here */ 132 CurrentEntry->NextFree = NULL; 133 } 134 135 /* remove handle from free list */ 136 HandleEntry = HandleTable->FreeHandles; 137 HandleTable->FreeHandles = HandleEntry->NextFree; 138 HandleEntry->NextFree = NULL; 139 140 if (Index) 141 { 142 *Index = ((ULONG)((ULONG_PTR)HandleEntry - (ULONG_PTR)HandleTable->CommittedHandles) / 143 HandleTable->SizeOfHandleTableEntry); 144 } 145 146 return HandleEntry; 147 } 148 149 150 /* 151 * @implemented 152 */ 153 BOOLEAN 154 NTAPI 155 RtlFreeHandle( 156 PRTL_HANDLE_TABLE HandleTable, 157 PRTL_HANDLE_TABLE_ENTRY Handle) 158 { 159 #if DBG 160 /* check if handle is valid */ 161 if (!RtlIsValidHandle(HandleTable, Handle)) 162 { 163 DPRINT1("Invalid Handle! HandleTable=0x%p, Handle=0x%p, Handle->Flags=0x%x\n", 164 HandleTable, Handle, Handle ? Handle->Flags : 0); 165 return FALSE; 166 } 167 #endif 168 169 /* clear handle */ 170 memset(Handle, 0, HandleTable->SizeOfHandleTableEntry); 171 172 /* add handle to free list */ 173 Handle->NextFree = HandleTable->FreeHandles; 174 HandleTable->FreeHandles = Handle; 175 176 return TRUE; 177 } 178 179 180 /* 181 * @implemented 182 */ 183 BOOLEAN 184 NTAPI 185 RtlIsValidHandle( 186 PRTL_HANDLE_TABLE HandleTable, 187 PRTL_HANDLE_TABLE_ENTRY Handle) 188 { 189 if ((HandleTable != NULL) 190 && (Handle >= HandleTable->CommittedHandles) 191 && (Handle < HandleTable->MaxReservedHandles) 192 && (Handle->Flags & RTL_HANDLE_VALID)) 193 { 194 return TRUE; 195 } 196 return FALSE; 197 } 198 199 200 /* 201 * @implemented 202 */ 203 BOOLEAN 204 NTAPI 205 RtlIsValidIndexHandle( 206 IN PRTL_HANDLE_TABLE HandleTable, 207 IN ULONG Index, 208 OUT PRTL_HANDLE_TABLE_ENTRY *Handle) 209 { 210 PRTL_HANDLE_TABLE_ENTRY InternalHandle; 211 212 DPRINT("RtlIsValidIndexHandle(HandleTable %p Index 0x%lx Handle %p)\n", HandleTable, Index, Handle); 213 214 if (HandleTable == NULL) 215 return FALSE; 216 217 DPRINT("Handles %p HandleSize 0x%lx\n", 218 HandleTable->CommittedHandles, HandleTable->SizeOfHandleTableEntry); 219 220 InternalHandle = (PRTL_HANDLE_TABLE_ENTRY)((ULONG_PTR)HandleTable->CommittedHandles + 221 (HandleTable->SizeOfHandleTableEntry * Index)); 222 if (!RtlIsValidHandle(HandleTable, InternalHandle)) 223 return FALSE; 224 225 DPRINT("InternalHandle %p\n", InternalHandle); 226 227 if (Handle != NULL) 228 *Handle = InternalHandle; 229 230 return TRUE; 231 } 232 233 /* EOF */ 234