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
RtlInitializeHandleTable(ULONG TableSize,ULONG HandleSize,PRTL_HANDLE_TABLE HandleTable)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
RtlDestroyHandleTable(PRTL_HANDLE_TABLE HandleTable)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
RtlAllocateHandle(PRTL_HANDLE_TABLE HandleTable,PULONG Index)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 uncommitted 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->CommittedHandles = (PRTL_HANDLE_TABLE_ENTRY)ArrayPointer;
93 HandleTable->UnCommittedHandles = (PRTL_HANDLE_TABLE_ENTRY)ArrayPointer;
94 HandleTable->MaxReservedHandles = (PRTL_HANDLE_TABLE_ENTRY)((ULONG_PTR)ArrayPointer + ArraySize);
95 }
96
97 /* Commit one reserved handle entry page */
98 ArraySize = PAGE_SIZE;
99 ArrayPointer = HandleTable->UnCommittedHandles;
100 Status = ZwAllocateVirtualMemory(NtCurrentProcess(),
101 &ArrayPointer,
102 0,
103 &ArraySize,
104 MEM_COMMIT,
105 PAGE_READWRITE);
106 if (!NT_SUCCESS(Status))
107 return NULL;
108
109 /* Update handle array pointers */
110 HandleTable->FreeHandles = (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
RtlFreeHandle(PRTL_HANDLE_TABLE HandleTable,PRTL_HANDLE_TABLE_ENTRY Handle)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
RtlIsValidHandle(PRTL_HANDLE_TABLE HandleTable,PRTL_HANDLE_TABLE_ENTRY Handle)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
RtlIsValidIndexHandle(IN PRTL_HANDLE_TABLE HandleTable,IN ULONG Index,OUT PRTL_HANDLE_TABLE_ENTRY * Handle)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