:pserver:cvsanon@mok.lvcm.com:/CVS/ReactOS reactos
[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 VOID STDCALL
35 RtlDestroyHandleTable(PRTL_HANDLE_TABLE HandleTable)
36 {
37    PVOID ArrayPointer;
38    ULONG ArraySize;
39
40    /* free handle array */
41    ArrayPointer = (PVOID)HandleTable->Handles;
42    ArraySize = (ULONG)HandleTable->Limit - (ULONG)HandleTable->Handles;
43    NtFreeVirtualMemory(NtCurrentProcess(),
44                        &ArrayPointer,
45                        &ArraySize,
46                        MEM_RELEASE);
47 }
48
49
50 PRTL_HANDLE STDCALL
51 RtlAllocateHandle(PRTL_HANDLE_TABLE HandleTable,
52                   PULONG Index)
53 {
54    RTL_HANDLE **pp_new,**pph,*ph;
55    NTSTATUS Status;
56    PRTL_HANDLE retval;
57    PVOID ArrayPointer;
58    ULONG ArraySize;
59
60    pp_new = &HandleTable->FirstFree;
61
62    if (HandleTable->FirstFree == NULL)
63      {
64         /* no free handle available */
65         if (HandleTable->LastUsed == NULL)
66           {
67              /* allocate handle array */
68              ArraySize = HandleTable->HandleSize * HandleTable->TableSize;
69              ArrayPointer = NULL;
70              Status = NtAllocateVirtualMemory(NtCurrentProcess(),
71                                               (PVOID*)&ArrayPointer,
72                                               0,
73                                               &ArraySize,
74                                               MEM_RESERVE | MEM_COMMIT,
75                                               PAGE_READWRITE);
76              if (!NT_SUCCESS(Status))
77                return NULL;
78
79              /* update handle array pointers */
80              HandleTable->Handles = (PRTL_HANDLE)ArrayPointer;
81              HandleTable->Limit = (PRTL_HANDLE)(ArrayPointer + ArraySize);
82              HandleTable->LastUsed = (PRTL_HANDLE)ArrayPointer;
83           }
84
85         /* build free list in handle array */
86         ph = HandleTable->LastUsed;
87         pph = pp_new;
88         while (ph < HandleTable->Limit)
89           {
90              *pph = ph;
91              pph = &ph->Next;
92              ph = (PRTL_HANDLE)((ULONG)ph + HandleTable->HandleSize);
93           }
94         *pph = 0;
95      }
96
97    /* remove handle from free list */
98    retval = *pp_new;
99    *pp_new = retval->Next;
100    retval->Next = NULL;
101
102    if (Index)
103      *Index = ((ULONG)retval - (ULONG)HandleTable->Handles) / HandleTable->HandleSize;
104
105    return retval;
106 }
107
108
109 BOOLEAN STDCALL
110 RtlFreeHandle(PRTL_HANDLE_TABLE HandleTable,
111               PRTL_HANDLE Handle)
112 {
113    /* check if handle is valid */
114    if (RtlIsValidHandle(HandleTable, Handle))
115      return FALSE;
116    
117    /* clear handle */
118    memset(Handle, 0, HandleTable->HandleSize);
119    
120    /* add handle to free list */
121    Handle->Next = HandleTable->FirstFree;
122    HandleTable->FirstFree = Handle;
123    
124    return TRUE;
125 }
126
127
128 BOOLEAN STDCALL
129 RtlIsValidHandle(PRTL_HANDLE_TABLE HandleTable,
130                  PRTL_HANDLE Handle)
131 {
132    if ((HandleTable != NULL)
133        && (Handle != NULL)
134        && (Handle >= HandleTable->Handles)
135        && (Handle < HandleTable->Limit))
136      return TRUE;
137    return FALSE;
138 }
139
140
141 BOOLEAN STDCALL
142 RtlIsValidIndexHandle(PRTL_HANDLE_TABLE HandleTable,
143                       PRTL_HANDLE *Handle,
144                       ULONG Index)
145 {
146    PRTL_HANDLE InternalHandle;
147
148    DPRINT("RtlIsValidIndexHandle(HandleTable %p Handle %p Index %x)\n", HandleTable, Handle, Index);
149
150    if (HandleTable == NULL)
151      return FALSE;
152
153    DPRINT("Handles %p HandleSize %x\n",
154           HandleTable->Handles, HandleTable->HandleSize);
155
156    InternalHandle = (PRTL_HANDLE)((ULONG)HandleTable->Handles + (HandleTable->HandleSize * Index));
157    if (RtlIsValidHandle(HandleTable, InternalHandle) == FALSE)
158      return FALSE;
159
160    DPRINT("InternalHandle %p\n", InternalHandle);
161
162    if (Handle != NULL)
163      *Handle = InternalHandle;
164
165   return TRUE;
166 }
167
168 /* EOF */