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