~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Wine Cross Reference
wine/dlls/ntdll/handletable.c

Version: ~ [ wine-1.5.30 ] ~ [ wine-1.5.29 ] ~ [ wine-1.5.28 ] ~ [ wine-1.5.27 ] ~ [ wine-1.5.26 ] ~ [ wine-1.5.25 ] ~ [ wine-1.5.24 ] ~ [ wine-1.5.23 ] ~ [ wine-1.5.22 ] ~ [ wine-1.5.21 ] ~ [ wine-1.5.20 ] ~ [ wine-1.5.19 ] ~ [ wine-1.5.18 ] ~ [ wine-1.5.17 ] ~ [ wine-1.5.16 ] ~ [ wine-1.5.15 ] ~ [ wine-1.5.14 ] ~ [ wine-1.5.13 ] ~ [ wine-1.5.12 ] ~ [ wine-1.5.11 ] ~ [ wine-1.5.10 ] ~ [ wine-1.5.9 ] ~ [ wine-1.5.8 ] ~ [ wine-1.5.7 ] ~ [ wine-1.4.1 ] ~ [ wine-1.5.6 ] ~ [ wine-1.5.5 ] ~ [ wine-1.5.4 ] ~ [ wine-1.5.3 ] ~ [ wine-1.5.2 ] ~ [ wine-1.5.1 ] ~ [ wine-1.5.0 ] ~ [ wine-1.4 ] ~ [ wine-1.4-rc6 ] ~ [ wine-1.4-rc5 ] ~ [ wine-1.4-rc4 ] ~ [ wine-1.4-rc3 ] ~ [ wine-1.4-rc2 ] ~ [ wine-1.4-rc1 ] ~ [ wine-1.3.37 ] ~ [ wine-1.3.36 ] ~ [ wine-1.3.35 ] ~ [ wine-1.3.34 ] ~ [ wine-1.3.33 ] ~ [ wine-1.3.32 ] ~ [ wine-1.3.31 ] ~ [ wine-1.3.30 ] ~ [ wine-1.3.29 ] ~ [ wine-1.3.28 ] ~ [ wine-1.3.27 ] ~ [ wine-1.3.26 ] ~ [ wine-1.3.25 ] ~ [ wine-1.3.24 ] ~ [ wine-1.3.23 ] ~ [ wine-1.3.22 ] ~ [ wine-1.3.21 ] ~ [ wine-1.3.20 ] ~ [ wine-1.3.19 ] ~ [ wine-1.3.18 ] ~ [ wine-1.2.3 ] ~ [ wine-1.3.17 ] ~ [ wine-1.3.16 ] ~ [ wine-1.3.15 ] ~ [ wine-1.3.14 ] ~ [ wine-1.3.13 ] ~ [ wine-1.3.12 ] ~ [ wine-1.3.11 ] ~ [ wine-1.3.10 ] ~ [ wine-1.3.9 ] ~ [ wine-1.2.2 ] ~ [ wine-1.3.8 ] ~ [ wine-1.3.7 ] ~ [ wine-1.3.6 ] ~ [ wine-1.3.5 ] ~ [ wine-1.2.1 ] ~ [ wine-1.3.4 ] ~ [ wine-1.3.3 ] ~ [ wine-1.3.2 ] ~ [ wine-1.3.1 ] ~ [ wine-1.3.0 ] ~ [ wine-1.2 ] ~ [ wine-1.2-rc7 ] ~ [ wine-1.2-rc6 ] ~ [ wine-1.2-rc5 ] ~ [ wine-1.2-rc4 ] ~ [ wine-1.2-rc3 ] ~ [ wine-1.2-rc2 ] ~ [ wine-1.2-rc1 ] ~ [ wine-1.1.44 ] ~ [ wine-1.1.43 ] ~ [ wine-1.1.42 ] ~ [ wine-1.1.41 ] ~ [ wine-1.1.40 ] ~ [ wine-1.1.39 ] ~ [ wine-1.1.38 ] ~ [ wine-1.1.37 ] ~ [ wine-1.1.36 ] ~ [ wine-1.1.35 ] ~ [ wine-1.1.34 ] ~ [ wine-1.1.33 ] ~ [ wine-1.1.32 ] ~ [ wine-1.1.31 ] ~ [ wine-1.1.30 ] ~ [ wine-1.1.29 ] ~ [ wine-1.1.28 ] ~ [ wine-1.1.27 ] ~ [ wine-1.1.26 ] ~ [ wine-1.1.25 ] ~ [ wine-1.1.24 ] ~ [ wine-1.1.23 ] ~ [ wine-1.1.22 ] ~ [ wine-1.1.21 ] ~ [ wine-1.1.20 ] ~ [ wine-1.1.19 ] ~ [ wine-1.1.18 ] ~ [ wine-1.1.17 ] ~ [ wine-1.1.16 ] ~ [ wine-1.1.15 ] ~ [ wine-1.1.14 ] ~ [ wine-1.1.13 ] ~ [ wine-1.1.12 ] ~ [ wine-1.1.11 ] ~ [ wine-1.1.10 ] ~ [ wine-1.1.9 ] ~ [ wine-1.1.8 ] ~ [ wine-1.1.7 ] ~ [ wine-1.0.1 ] ~ [ wine-1.1.6 ] ~ [ wine-1.1.5 ] ~ [ wine-1.1.4 ] ~ [ wine-1.1.3 ] ~ [ wine-1.1.2 ] ~ [ wine-1.1.1 ] ~ [ wine-1.1.0 ] ~ [ wine-1.0 ] ~

  1 /*
  2  * Handle Tables
  3  *
  4  * Copyright (C) 2004 Robert Shearman
  5  *
  6  * This library is free software; you can redistribute it and/or
  7  * modify it under the terms of the GNU Lesser General Public
  8  * License as published by the Free Software Foundation; either
  9  * version 2.1 of the License, or (at your option) any later version.
 10  *
 11  * This library is distributed in the hope that it will be useful,
 12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 14  * Lesser General Public License for more details.
 15  *
 16  * You should have received a copy of the GNU Lesser General Public
 17  * License along with this library; if not, write to the Free Software
 18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 19  */
 20 
 21 #include <stdarg.h>
 22 
 23 #include "ntstatus.h"
 24 #define WIN32_NO_STATUS
 25 #include "windef.h"
 26 #include "winternl.h"
 27 #include "wine/debug.h"
 28 #include "ntdll_misc.h"
 29 
 30 WINE_DEFAULT_DEBUG_CHANNEL(ntdll);
 31 
 32 /**************************************************************************
 33  *      RtlInitializeHandleTable   (NTDLL.@)
 34  *
 35  * Initializes a handle table.
 36  *
 37  * PARAMS
 38  *  MaxHandleCount [I] The maximum number of handles the handle table will support.
 39  *  HandleSize     [I] The size of each handle.
 40  *  HandleTable    [I/O] The handle table.
 41  *
 42  * RETURNS
 43  *  Nothing.
 44  *
 45  * SEE
 46  *  RtlDestroyHandleTable().
 47  */
 48 void WINAPI RtlInitializeHandleTable(ULONG MaxHandleCount, ULONG HandleSize, RTL_HANDLE_TABLE * HandleTable)
 49 {
 50     TRACE("(%u, %u, %p)\n", MaxHandleCount, HandleSize, HandleTable);
 51 
 52     memset(HandleTable, 0, sizeof(*HandleTable));
 53     HandleTable->MaxHandleCount = MaxHandleCount;
 54     HandleTable->HandleSize = HandleSize;
 55 }
 56 
 57 /**************************************************************************
 58  *      RtlDestroyHandleTable   (NTDLL.@)
 59  *
 60  * Destroys a handle table and frees associated resources.
 61  *
 62  * PARAMS
 63  *  HandleTable    [I] The handle table.
 64  *
 65  * RETURNS
 66  *  Any status code returned by NtFreeVirtualMemory().
 67  *
 68  * NOTES
 69  *  The native version of this API doesn't free the virtual memory that has
 70  *  been previously reserved, only the committed memory. There is no harm
 71  *  in also freeing the reserved memory because it won't have been handed out
 72  *  to any callers. I believe it is "more polite" to free everything.
 73  *
 74  * SEE
 75  *  RtlInitializeHandleTable().
 76  */
 77 NTSTATUS WINAPI RtlDestroyHandleTable(RTL_HANDLE_TABLE * HandleTable)
 78 {
 79     SIZE_T Size = 0;
 80 
 81     TRACE("(%p)\n", HandleTable);
 82 
 83     /* native version only releases committed memory, but we also release reserved */
 84     return NtFreeVirtualMemory(
 85         NtCurrentProcess(),
 86         &HandleTable->FirstHandle,
 87         &Size,
 88         MEM_RELEASE);
 89 }
 90 
 91 /**************************************************************************
 92  *      RtlpAllocateSomeHandles   (internal)
 93  *
 94  * Reserves memory for the handles if not previously done and commits memory
 95  * for a batch of handles if none are free and adds them to the free list.
 96  *
 97  * PARAMS
 98  *  HandleTable    [I/O] The handle table.
 99  *
100  * RETURNS
101  *  NTSTATUS code.
102  */
103 static NTSTATUS RtlpAllocateSomeHandles(RTL_HANDLE_TABLE * HandleTable)
104 {
105     NTSTATUS status;
106     if (!HandleTable->FirstHandle)
107     {
108         PVOID FirstHandleAddr = NULL;
109         SIZE_T MaxSize = HandleTable->MaxHandleCount * HandleTable->HandleSize;
110 
111         /* reserve memory for the handles, but don't commit it yet because we
112          * probably won't use most of it and it will use up physical memory */
113         status = NtAllocateVirtualMemory(
114             NtCurrentProcess(),
115             &FirstHandleAddr,
116             0,
117             &MaxSize,
118             MEM_RESERVE,
119             PAGE_READWRITE);
120         if (status != STATUS_SUCCESS)
121             return status;
122         HandleTable->FirstHandle = FirstHandleAddr;
123         HandleTable->ReservedMemory = HandleTable->FirstHandle;
124         HandleTable->MaxHandle = (char *)HandleTable->FirstHandle + MaxSize;
125     }
126     if (!HandleTable->NextFree)
127     {
128         SIZE_T Offset, CommitSize = 4096; /* one page */
129         RTL_HANDLE * FreeHandle = NULL;
130         PVOID NextAvailAddr = HandleTable->ReservedMemory;
131 
132         if (HandleTable->ReservedMemory >= HandleTable->MaxHandle)
133             return STATUS_NO_MEMORY; /* the handle table is completely full */
134 
135         status = NtAllocateVirtualMemory(
136             NtCurrentProcess(),
137             &NextAvailAddr,
138             0,
139             &CommitSize,
140             MEM_COMMIT,
141             PAGE_READWRITE);
142         if (status != STATUS_SUCCESS)
143             return status;
144 
145         for (Offset = 0; Offset < CommitSize; Offset += HandleTable->HandleSize)
146         {
147             /* make sure we don't go over handle limit, even if we can
148              * because of rounding of the table size up to the next page
149              * boundary */
150             if ((char *)HandleTable->ReservedMemory + Offset >= (char *)HandleTable->MaxHandle)
151                 break;
152 
153             FreeHandle = (RTL_HANDLE *)((char *)HandleTable->ReservedMemory + Offset);
154 
155             FreeHandle->Next = (RTL_HANDLE *)((char *)HandleTable->ReservedMemory + 
156                 Offset + HandleTable->HandleSize);
157         }
158 
159         /* shouldn't happen because we already test for this above, but
160          * handle it just in case */
161         if (!FreeHandle)
162             return STATUS_NO_MEMORY;
163 
164         /* set the last handle's Next pointer to NULL so that when we run
165          * out of free handles we trigger another commit of memory and
166          * initialize the free pointers */
167         FreeHandle->Next = NULL;
168 
169         HandleTable->NextFree = HandleTable->ReservedMemory;
170 
171         HandleTable->ReservedMemory = (char *)HandleTable->ReservedMemory + CommitSize;
172     }
173     return STATUS_SUCCESS;
174 }
175 
176 /**************************************************************************
177  *      RtlAllocateHandle   (NTDLL.@)
178  *
179  * Allocates a handle from the handle table.
180  *
181  * PARAMS
182  *  HandleTable    [I/O] The handle table.
183  *  HandleIndex    [O] Index of the handle returned. Optional.
184  *
185  * RETURNS
186  *  Success: Pointer to allocated handle.
187  *  Failure: NULL.
188  *
189  * NOTES
190  *  A valid handle must have the bit set as indicated in the code below 
191  *  otherwise subsequent RtlIsValidHandle() calls will fail.
192  *
193  *  static inline void RtlpMakeHandleAllocated(RTL_HANDLE * Handle)
194  *  {
195  *    ULONG_PTR *AllocatedBit = (ULONG_PTR *)(&Handle->Next);
196  *    *AllocatedBit = *AllocatedBit | 1;
197  *  }
198  *
199  * SEE
200  *  RtlFreeHandle().
201  */
202 RTL_HANDLE * WINAPI RtlAllocateHandle(RTL_HANDLE_TABLE * HandleTable, ULONG * HandleIndex)
203 {
204     RTL_HANDLE * ret;
205 
206     TRACE("(%p, %p)\n", HandleTable, HandleIndex);
207 
208     if (!HandleTable->NextFree && RtlpAllocateSomeHandles(HandleTable) != STATUS_SUCCESS)
209         return NULL;
210 
211     ret = HandleTable->NextFree;
212     HandleTable->NextFree = ret->Next;
213 
214     if (HandleIndex)
215         *HandleIndex = (ULONG)(((PCHAR)ret - (PCHAR)HandleTable->FirstHandle) / HandleTable->HandleSize);
216 
217     return ret;
218 }
219 
220 /**************************************************************************
221  *      RtlFreeHandle   (NTDLL.@)
222  *
223  * Frees an allocated handle.
224  *
225  * PARAMS
226  *  HandleTable    [I/O] The handle table.
227  *  Handle         [I] The handle to be freed.
228  *
229  * RETURNS
230  *  Success: TRUE.
231  *  Failure: FALSE.
232  *
233  * SEE
234  *  RtlAllocateHandle().
235  */
236 BOOLEAN WINAPI RtlFreeHandle(RTL_HANDLE_TABLE * HandleTable, RTL_HANDLE * Handle)
237 {
238     TRACE("(%p, %p)\n", HandleTable, Handle);
239     /* NOTE: we don't validate the handle and we don't make Handle->Next even
240      * again to signal that it is no longer in user - that is done as a side
241      * effect of setting Handle->Next to the previously next free handle in
242      * the handle table */
243     memset(Handle, 0, HandleTable->HandleSize);
244     Handle->Next = HandleTable->NextFree;
245     HandleTable->NextFree = Handle;
246     return TRUE;
247 }
248 
249 /**************************************************************************
250  *      RtlIsValidHandle   (NTDLL.@)
251  *
252  * Determines whether a handle is valid or not.
253  *
254  * PARAMS
255  *  HandleTable    [I] The handle table.
256  *  Handle         [I] The handle to be tested.
257  *
258  * RETURNS
259  *  Valid: TRUE.
260  *  Invalid: FALSE.
261  */
262 BOOLEAN WINAPI RtlIsValidHandle(const RTL_HANDLE_TABLE * HandleTable, const RTL_HANDLE * Handle)
263 {
264     TRACE("(%p, %p)\n", HandleTable, Handle);
265     /* make sure handle is within used region and that it is aligned on
266      * a HandleTable->HandleSize boundary and that Handle->Next is odd,
267      * indicating that the handle is active */
268     if ((Handle >= (RTL_HANDLE *)HandleTable->FirstHandle) &&
269       (Handle < (RTL_HANDLE *)HandleTable->ReservedMemory) &&
270       !((ULONG_PTR)Handle & (HandleTable->HandleSize - 1)) &&
271       ((ULONG_PTR)Handle->Next & 1))
272         return TRUE;
273     else
274         return FALSE;
275 }
276 
277 /**************************************************************************
278  *      RtlIsValidIndexHandle   (NTDLL.@)
279  *
280  * Determines whether a handle index is valid or not.
281  *
282  * PARAMS
283  *  HandleTable    [I] The handle table.
284  *  Index          [I] The index of the handle to be tested.
285  *  ValidHandle    [O] The handle Index refers to.
286  *
287  * RETURNS
288  *  Valid: TRUE.
289  *  Invalid: FALSE.
290  */
291 BOOLEAN WINAPI RtlIsValidIndexHandle(const RTL_HANDLE_TABLE * HandleTable, ULONG Index, RTL_HANDLE ** ValidHandle)
292 {
293     RTL_HANDLE * Handle;
294 
295     TRACE("(%p, %u, %p)\n", HandleTable, Index, ValidHandle);
296     Handle = (RTL_HANDLE *)
297         ((char *)HandleTable->FirstHandle + Index * HandleTable->HandleSize);
298 
299     if (RtlIsValidHandle(HandleTable, Handle))
300     {
301         *ValidHandle = Handle;
302         return TRUE;
303     }
304     return FALSE;
305 }
306 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.