update for HEAD-2003091401
[reactos.git] / lib / ntdll / 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 <ntdll/rtl.h>
14
15 #define NDEBUG
16 #include <ntdll/ntdll.h>
17
18 /* FUNCTIONS *****************************************************************/
19
20 VOID STDCALL
21 RtlInitializeHandleTable(ULONG TableSize,
22                          ULONG HandleSize,
23                          PRTL_HANDLE_TABLE HandleTable)
24 {
25    /* initialize handle table */
26    memset(HandleTable,
27           0,
28           sizeof(RTL_HANDLE_TABLE));
29    HandleTable->TableSize = TableSize;
30    HandleTable->HandleSize = HandleSize;
31 }
32
33
34 /*
35  * @implemented
36  */
37 VOID STDCALL
38 RtlDestroyHandleTable(PRTL_HANDLE_TABLE HandleTable)
39 {
40    PVOID ArrayPointer;
41    ULONG ArraySize;
42
43    /* free handle array */
44    ArrayPointer = (PVOID)HandleTable->Handles;
45    ArraySize = (ULONG)HandleTable->Limit - (ULONG)HandleTable->Handles;
46    NtFreeVirtualMemory(NtCurrentProcess(),
47                        &ArrayPointer,
48                        &ArraySize,
49                        MEM_RELEASE);
50 }
51
52
53 /*
54  * @implemented
55  */
56 PRTL_HANDLE STDCALL
57 RtlAllocateHandle(PRTL_HANDLE_TABLE HandleTable,
58                   PULONG Index)
59 {
60    RTL_HANDLE **pp_new,**pph,*ph;
61    NTSTATUS Status;
62    PRTL_HANDLE retval;
63    PVOID ArrayPointer;
64    ULONG ArraySize;
65
66    pp_new = &HandleTable->FirstFree;
67
68    if (HandleTable->FirstFree == NULL)
69      {
70         /* no free handle available */
71         if (HandleTable->LastUsed == NULL)
72           {
73              /* allocate handle array */
74              ArraySize = HandleTable->HandleSize * HandleTable->TableSize;
75              ArrayPointer = NULL;
76              Status = NtAllocateVirtualMemory(NtCurrentProcess(),
77                                               (PVOID*)&ArrayPointer,
78                                               0,
79                                               &ArraySize,
80                                               MEM_RESERVE | MEM_COMMIT,
81                                               PAGE_READWRITE);
82              if (!NT_SUCCESS(Status))
83                return NULL;
84
85              /* update handle array pointers */
86              HandleTable->Handles = (PRTL_HANDLE)ArrayPointer;
87              HandleTable->Limit = (PRTL_HANDLE)(ArrayPointer + ArraySize);
88              HandleTable->LastUsed = (PRTL_HANDLE)ArrayPointer;
89           }
90
91         /* build free list in handle array */
92         ph = HandleTable->LastUsed;
93         pph = pp_new;
94         while (ph < HandleTable->Limit)
95           {
96              *pph = ph;
97              pph = &ph->Next;
98              ph = (PRTL_HANDLE)((ULONG)ph + HandleTable->HandleSize);
99           }
100         *pph = 0;
101      }
102
103    /* remove handle from free list */
104    retval = *pp_new;
105    *pp_new = retval->Next;
106    retval->Next = NULL;
107
108    if (Index)
109      *Index = ((ULONG)retval - (ULONG)HandleTable->Handles) / HandleTable->HandleSize;
110
111    return retval;
112 }
113
114
115 /*
116  * @implemented
117  */
118 BOOLEAN STDCALL
119 RtlFreeHandle(PRTL_HANDLE_TABLE HandleTable,
120               PRTL_HANDLE Handle)
121 {
122    /* check if handle is valid */
123    if (RtlIsValidHandle(HandleTable, Handle))
124      return FALSE;
125    
126    /* clear handle */
127    memset(Handle, 0, HandleTable->HandleSize);
128    
129    /* add handle to free list */
130    Handle->Next = HandleTable->FirstFree;
131    HandleTable->FirstFree = Handle;
132    
133    return TRUE;
134 }
135
136
137 /*
138  * @implemented
139  */
140 BOOLEAN STDCALL
141 RtlIsValidHandle(PRTL_HANDLE_TABLE HandleTable,
142                  PRTL_HANDLE Handle)
143 {
144    if ((HandleTable != NULL)
145        && (Handle != NULL)
146        && (Handle >= HandleTable->Handles)
147        && (Handle < HandleTable->Limit))
148      return TRUE;
149    return FALSE;
150 }
151
152
153 /*
154  * @implemented
155  */
156 BOOLEAN STDCALL
157 RtlIsValidIndexHandle(PRTL_HANDLE_TABLE HandleTable,
158                       PRTL_HANDLE *Handle,
159                       ULONG Index)
160 {
161    PRTL_HANDLE InternalHandle;
162
163    DPRINT("RtlIsValidIndexHandle(HandleTable %p Handle %p Index %x)\n", HandleTable, Handle, Index);
164
165    if (HandleTable == NULL)
166      return FALSE;
167
168    DPRINT("Handles %p HandleSize %x\n",
169           HandleTable->Handles, HandleTable->HandleSize);
170
171    InternalHandle = (PRTL_HANDLE)((ULONG)HandleTable->Handles + (HandleTable->HandleSize * Index));
172    if (RtlIsValidHandle(HandleTable, InternalHandle) == FALSE)
173      return FALSE;
174
175    DPRINT("InternalHandle %p\n", InternalHandle);
176
177    if (Handle != NULL)
178      *Handle = InternalHandle;
179
180   return TRUE;
181 }
182
183 /* EOF */