[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 *pp_new, *pph, ph;
64 NTSTATUS Status;
65 PRTL_HANDLE_TABLE_ENTRY retval;
66 PVOID ArrayPointer;
67 SIZE_T ArraySize;
68
69 pp_new = &HandleTable->FreeHandles;
70
71 if (HandleTable->FreeHandles == NULL)
72 {
73 /* no free handle available */
74 if (HandleTable->UnCommittedHandles == NULL)
75 {
76 /* allocate handle array */
77 ArraySize = HandleTable->SizeOfHandleTableEntry * HandleTable->MaximumNumberOfHandles;
78 ArrayPointer = NULL;
79
80 /* FIXME - only reserve handles here! */
81 Status = NtAllocateVirtualMemory(NtCurrentProcess(),
82 (PVOID*)&ArrayPointer,
83 0,
84 &ArraySize,
85 MEM_RESERVE | MEM_COMMIT,
86 PAGE_READWRITE);
87 if (!NT_SUCCESS(Status))
88 return NULL;
89
90 /* update handle array pointers */
91 HandleTable->FreeHandles = (PRTL_HANDLE_TABLE_ENTRY)ArrayPointer;
92 HandleTable->MaxReservedHandles = (PRTL_HANDLE_TABLE_ENTRY)((ULONG_PTR)ArrayPointer + ArraySize);
93 HandleTable->CommittedHandles = (PRTL_HANDLE_TABLE_ENTRY)ArrayPointer;
94 HandleTable->UnCommittedHandles = (PRTL_HANDLE_TABLE_ENTRY)ArrayPointer;
95 }
96
97 /* FIXME - should check if handles need to be committed */
98
99 /* build free list in handle array */
100 ph = HandleTable->FreeHandles;
101 pph = pp_new;
102 while (ph < HandleTable->MaxReservedHandles)
103 {
104 *pph = ph;
105 pph = &ph->NextFree;
106 ph = (PRTL_HANDLE_TABLE_ENTRY)((ULONG_PTR)ph + HandleTable->SizeOfHandleTableEntry);
107 }
108 *pph = 0;
109 }
110
111 /* remove handle from free list */
112 retval = *pp_new;
113 *pp_new = retval->NextFree;
114 retval->NextFree = NULL;
115
116 if (Index)
117 {
118 *Index = ((ULONG)((ULONG_PTR)retval - (ULONG_PTR)HandleTable->CommittedHandles) /
119 HandleTable->SizeOfHandleTableEntry);
120 }
121
122 return retval;
123 }
124
125
126 /*
127 * @implemented
128 */
129 BOOLEAN
130 NTAPI
131 RtlFreeHandle(
132 PRTL_HANDLE_TABLE HandleTable,
133 PRTL_HANDLE_TABLE_ENTRY Handle)
134 {
135 #if DBG
136 /* check if handle is valid */
137 if (!RtlIsValidHandle(HandleTable, Handle))
138 {
139 DPRINT1("Invalid Handle! HandleTable=0x%p, Handle=0x%p, Handle->Flags=0x%x\n",
140 HandleTable, Handle, Handle ? Handle->Flags : 0);
141 return FALSE;
142 }
143 #endif
144
145 /* clear handle */
146 memset(Handle, 0, HandleTable->SizeOfHandleTableEntry);
147
148 /* add handle to free list */
149 Handle->NextFree = HandleTable->FreeHandles;
150 HandleTable->FreeHandles = Handle;
151
152 return TRUE;
153 }
154
155
156 /*
157 * @implemented
158 */
159 BOOLEAN
160 NTAPI
161 RtlIsValidHandle(
162 PRTL_HANDLE_TABLE HandleTable,
163 PRTL_HANDLE_TABLE_ENTRY Handle)
164 {
165 if ((HandleTable != NULL)
166 && (Handle >= HandleTable->CommittedHandles)
167 && (Handle < HandleTable->MaxReservedHandles)
168 && (Handle->Flags & RTL_HANDLE_VALID))
169 {
170 return TRUE;
171 }
172 return FALSE;
173 }
174
175
176 /*
177 * @implemented
178 */
179 BOOLEAN
180 NTAPI
181 RtlIsValidIndexHandle(
182 IN PRTL_HANDLE_TABLE HandleTable,
183 IN ULONG Index,
184 OUT PRTL_HANDLE_TABLE_ENTRY *Handle)
185 {
186 PRTL_HANDLE_TABLE_ENTRY InternalHandle;
187
188 DPRINT("RtlIsValidIndexHandle(HandleTable %p Index 0x%lx Handle %p)\n", HandleTable, Index, Handle);
189
190 if (HandleTable == NULL)
191 return FALSE;
192
193 DPRINT("Handles %p HandleSize 0x%lx\n",
194 HandleTable->CommittedHandles, HandleTable->SizeOfHandleTableEntry);
195
196 InternalHandle = (PRTL_HANDLE_TABLE_ENTRY)((ULONG_PTR)HandleTable->CommittedHandles +
197 (HandleTable->SizeOfHandleTableEntry * Index));
198 if (!RtlIsValidHandle(HandleTable, InternalHandle))
199 return FALSE;
200
201 DPRINT("InternalHandle %p\n", InternalHandle);
202
203 if (Handle != NULL)
204 *Handle = InternalHandle;
205
206 return TRUE;
207 }
208
209 /* EOF */