update for HEAD-2003091401
[reactos.git] / ntoskrnl / rtl / handle.c
1 /* $Id$
2  *
3  * COPYRIGHT:         See COPYING in the top level directory
4  * PROJECT:           ReactOS kernel
5  * PURPOSE:           Handle table
6  * FILE:              lib/ntdll/rtl/handle.c
7  * PROGRAMER:         Eric Kohl <ekohl@rz-online.de>
8  */
9
10 /* INCLUDES ******************************************************************/
11
12 #include <ddk/ntddk.h>
13 #include <internal/handle.h>
14 #include <internal/pool.h>
15
16 #define NDEBUG
17 #include <internal/debug.h>
18
19
20 #define TAG_HDTB  TAG('H', 'D', 'T', 'B')
21
22
23 static BOOLEAN
24 RtlpIsValidHandle(PRTL_HANDLE_TABLE HandleTable, PRTL_HANDLE Handle);
25 static BOOLEAN
26 RtlpIsValidIndexHandle(PRTL_HANDLE_TABLE HandleTable, PRTL_HANDLE *Handle, ULONG Index);
27
28
29 /* FUNCTIONS *****************************************************************/
30
31 VOID
32 RtlpInitializeHandleTable(ULONG TableSize,
33                           PRTL_HANDLE_TABLE HandleTable)
34 {
35    /* initialize handle table */
36    memset(HandleTable,
37           0,
38           sizeof(RTL_HANDLE_TABLE));
39    HandleTable->TableSize = TableSize;
40 }
41
42
43 VOID
44 RtlpDestroyHandleTable(PRTL_HANDLE_TABLE HandleTable)
45 {
46    ExFreePool((PVOID)HandleTable->Handles);
47 }
48
49
50 BOOLEAN
51 RtlpAllocateHandle(PRTL_HANDLE_TABLE HandleTable,
52                    PVOID Object,
53                    PULONG Index)
54 {
55    RTL_HANDLE **pp_new,**pph,*ph;
56    PRTL_HANDLE retval;
57    PVOID ArrayPointer;
58    ULONG ArraySize;
59
60    if (Index == NULL)
61      return FALSE;
62
63    pp_new = &HandleTable->FirstFree;
64
65    if (HandleTable->FirstFree == NULL)
66      {
67         /* no free handle available */
68         if (HandleTable->LastUsed == NULL)
69           {
70              /* allocate handle array */
71              ArraySize = sizeof(RTL_HANDLE) * HandleTable->TableSize;
72              ArrayPointer = ExAllocatePoolWithTag(NonPagedPool,
73                                                   ArraySize,
74                                                   TAG_HDTB);
75              if (ArrayPointer == NULL)
76                return FALSE;
77
78              /* update handle array pointers */
79              HandleTable->Handles = (PRTL_HANDLE)ArrayPointer;
80              HandleTable->Limit = (PRTL_HANDLE)(ArrayPointer + ArraySize);
81              HandleTable->LastUsed = (PRTL_HANDLE)ArrayPointer;
82           }
83
84         /* build free list in handle array */
85         ph = HandleTable->LastUsed;
86         pph = pp_new;
87         while (ph < HandleTable->Limit)
88           {
89              *pph = ph;
90              pph = &ph->Next;
91              ph = (PRTL_HANDLE)((ULONG)ph + sizeof(RTL_HANDLE));
92           }
93         *pph = 0;
94      }
95
96    /* remove handle from free list */
97    retval = *pp_new;
98    *pp_new = retval->Next;
99    retval->Next = NULL;
100    retval->Object = Object;
101
102    *Index = ((ULONG)retval - (ULONG)HandleTable->Handles) / sizeof(RTL_HANDLE);
103
104    return TRUE;
105 }
106
107
108 BOOLEAN
109 RtlpFreeHandle(PRTL_HANDLE_TABLE HandleTable,
110                ULONG Index)
111 {
112    PRTL_HANDLE Handle;
113
114    /* check if handle is valid */
115    if (! RtlpIsValidIndexHandle(HandleTable,
116                          &Handle,
117                          Index))
118      return FALSE;
119    
120    /* clear handle */
121    memset(Handle, 0, sizeof(RTL_HANDLE));
122    
123    /* add handle to free list */
124    Handle->Next = HandleTable->FirstFree;
125    HandleTable->FirstFree = Handle;
126    
127    return TRUE;
128 }
129
130
131 static BOOLEAN
132 RtlpIsValidHandle(PRTL_HANDLE_TABLE HandleTable,
133                   PRTL_HANDLE Handle)
134 {
135    if ((HandleTable != NULL)
136        && (Handle != NULL)
137        && (Handle >= HandleTable->Handles)
138        && (Handle < HandleTable->Limit))
139      return TRUE;
140    return FALSE;
141 }
142
143
144 static BOOLEAN
145 RtlpIsValidIndexHandle(PRTL_HANDLE_TABLE HandleTable,
146                        PRTL_HANDLE *Handle,
147                        ULONG Index)
148 {
149    PRTL_HANDLE InternalHandle;
150
151    DPRINT("RtlpIsValidIndexHandle(HandleTable %p Handle %p Index %x)\n", HandleTable, Handle, Index);
152
153    if (HandleTable == NULL)
154      return FALSE;
155
156    DPRINT("Handles %p\n", HandleTable->Handles);
157
158    InternalHandle = (PRTL_HANDLE)((ULONG)HandleTable->Handles + sizeof(RTL_HANDLE) * Index);
159    if (RtlpIsValidHandle(HandleTable, InternalHandle) == FALSE)
160      return FALSE;
161
162    DPRINT("InternalHandle %p\n", InternalHandle);
163
164    if (Handle != NULL)
165      *Handle = InternalHandle;
166
167   return TRUE;
168 }
169
170 PVOID
171 RtlpMapHandleToPointer(PRTL_HANDLE_TABLE HandleTable,
172                        ULONG Index)
173 {
174    PRTL_HANDLE Handle;
175
176    if (!RtlpIsValidIndexHandle(HandleTable,
177                                &Handle,
178                                Index))
179      {
180         return NULL;
181      }
182
183    return Handle->Object;
184 }
185
186 /* EOF */