source: trunk/src/rsaenh/handle.c@ 21971

Last change on this file since 21971 was 21971, checked in by dmik, 14 years ago

Fix debug build break (r21967 regression).

Some code doesn't actually use RTL_CRITICAL_SECTION which
contains the needed debug fields.

File size: 13.9 KB
Line 
1/*
2 * dlls/rsaenh/handle.c
3 * Support code to manage HANDLE tables.
4 *
5 * Copyright 1998 Alexandre Julliard
6 * Copyright 2002-2004 Mike McCormack for CodeWeavers
7 * Copyright 2004 Michael Jung
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 */
23
24#include <string.h>
25#include <stdarg.h>
26
27#include "windef.h"
28#include "winbase.h"
29#include "handle.h"
30
31#include "wine/debug.h"
32
33WINE_DEFAULT_DEBUG_CHANNEL(handle);
34
35#define HANDLE2INDEX(h) ((h)-1)
36#define INDEX2HANDLE(i) ((i)+1)
37
38/******************************************************************************
39 * init_handle_table
40 *
41 * Initializes the HANDLETBL structure pointed to by lpTable
42 *
43 * PARAMS
44 * lpTable [I] Pointer to the HANDLETBL structure, which is to be initalized.
45 *
46 * NOTES
47 * Note that alloc_handle_table calls init_handle_table on it's own, which
48 * means that you only have to call init_handle_table, if you use a global
49 * variable of type HANDLETBL for your handle table. However, in this
50 * case you have to call destroy_handle_table when you don't need the table
51 * any more.
52 */
53void init_handle_table(HANDLETBL *lpTable)
54{
55 TRACE("(lpTable=%p)\n", lpTable);
56
57 lpTable->paEntries = NULL;
58 lpTable->iEntries = 0;
59 lpTable->iFirstFree = 0;
60 InitializeCriticalSection(&lpTable->mutex);
61#ifdef DEBUG
62 //lpTable->mutex.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": HANDLETBL.mutex");
63#endif
64}
65
66/******************************************************************************
67 * destroy_handle_table
68 *
69 * Destroys the handle table.
70 *
71 * PARAMS
72 * lpTable [I] Pointer to the handle table, which is to be destroyed.
73 *
74 * NOTES
75 * Note that release_handle_table takes care of this.
76 */
77void destroy_handle_table(HANDLETBL *lpTable)
78{
79 TRACE("(lpTable=%p)\n", lpTable);
80
81 HeapFree(GetProcessHeap(), 0, lpTable->paEntries);
82#ifdef DEBUG
83 //lpTable->mutex.DebugInfo->Spare[0] = 0;
84#endif
85 DeleteCriticalSection(&lpTable->mutex);
86}
87
88/******************************************************************************
89 * is_valid_handle
90 *
91 * Tests if handle is valid given the specified handle table
92 *
93 * PARAMS
94 * lpTable [I] Pointer to the handle table, with respect to which the handle's
95 * validness is tested.
96 * handle [I] The handle tested for validness.
97 * dwType [I] A magic value that identifies the referenced object's type.
98 *
99 * RETURNS
100 * non zero, if handle is valid.
101 * zero, if handle is not valid.
102 */
103int is_valid_handle(HANDLETBL *lpTable, HCRYPTKEY handle, DWORD dwType)
104{
105 unsigned int index = HANDLE2INDEX(handle);
106 int ret = 0;
107
108 TRACE("(lpTable=%p, handle=%ld)\n", lpTable, handle);
109
110 EnterCriticalSection(&lpTable->mutex);
111
112 /* We don't use zero handle values */
113 if (!handle) goto exit;
114
115 /* Check for index out of table bounds */
116 if (index >= lpTable->iEntries) goto exit;
117
118 /* Check if this handle is currently allocated */
119 if (!lpTable->paEntries[index].pObject) goto exit;
120
121 /* Check if this handle references an object of the correct type. */
122 if (lpTable->paEntries[index].pObject->dwType != dwType) goto exit;
123
124 ret = 1;
125exit:
126 LeaveCriticalSection(&lpTable->mutex);
127 return ret;
128}
129
130/******************************************************************************
131 * release_all_handles
132 *
133 * Releases all valid handles in the given handle table and shrinks the table
134 * to zero size.
135 *
136 * PARAMS
137 * lpTable [I] The table of which all valid handles shall be released.
138 */
139static void release_all_handles(HANDLETBL *lpTable)
140{
141 unsigned int i;
142
143 TRACE("(lpTable=%p)\n", lpTable);
144
145 EnterCriticalSection(&lpTable->mutex);
146 for (i=0; i<lpTable->iEntries; i++)
147 if (lpTable->paEntries[i].pObject)
148 release_handle(lpTable, lpTable->paEntries[i].pObject->dwType, INDEX2HANDLE(i));
149 LeaveCriticalSection(&lpTable->mutex);
150}
151
152/******************************************************************************
153 * alloc_handle_table
154 *
155 * Allocates a new handle table
156 *
157 * PARAMS
158 * lplpTable [O] Pointer to the variable, to which the pointer to the newly
159 * allocated handle table is written.
160 * RETURNS
161 * non zero, if successful
162 * zero, if not successful (out of process heap memory)
163 *
164 * NOTES
165 * If all you need is a single handle table, you may as well declare a global
166 * variable of type HANDLETBL and call init_handle_table on your own.
167 */
168int alloc_handle_table(HANDLETBL **lplpTable)
169{
170 TRACE("(lplpTable=%p)\n", lplpTable);
171
172 *lplpTable = HeapAlloc(GetProcessHeap(), 0, sizeof(HANDLETBL));
173 if (*lplpTable)
174 {
175 init_handle_table(*lplpTable);
176 return 1;
177 }
178 else
179 return 0;
180}
181
182/******************************************************************************
183 * release_handle_table
184 *
185 * Releases a handle table and frees the resources it used.
186 *
187 * PARAMS
188 * lpTable [I] Pointer to the handle table, which is to be released.
189 *
190 * RETURNS
191 * non zero, if successful
192 * zero, if not successful
193 *
194 * NOTES
195 * All valid handles still in the table are released also.
196 */
197int release_handle_table(HANDLETBL *lpTable)
198{
199 TRACE("(lpTable=%p)\n", lpTable);
200
201 release_all_handles(lpTable);
202 destroy_handle_table(lpTable);
203 return HeapFree(GetProcessHeap(), 0, lpTable);
204}
205
206/******************************************************************************
207 * grow_handle_table [Internal]
208 *
209 * Grows the number of entries in the given table by TABLE_SIZE_INCREMENT
210 *
211 * PARAMS
212 * lpTable [I] Pointer to the table, which is to be grown
213 *
214 * RETURNS
215 * non zero, if successful
216 * zero, if not successful (out of memory on process heap)
217 *
218 * NOTES
219 * This is a support function for alloc_handle. Do not call!
220 */
221static int grow_handle_table(HANDLETBL *lpTable)
222{
223 HANDLETBLENTRY *newEntries;
224 unsigned int i, newIEntries;
225
226 newIEntries = lpTable->iEntries + TABLE_SIZE_INCREMENT;
227
228 newEntries = HeapAlloc(GetProcessHeap(), 0, sizeof(HANDLETBLENTRY)*newIEntries);
229 if (!newEntries)
230 return 0;
231
232 if (lpTable->paEntries)
233 {
234 memcpy(newEntries, lpTable->paEntries, sizeof(HANDLETBLENTRY)*lpTable->iEntries);
235 HeapFree(GetProcessHeap(), 0, lpTable->paEntries);
236 }
237
238 for (i=lpTable->iEntries; i<newIEntries; i++)
239 {
240 newEntries[i].pObject = NULL;
241 newEntries[i].iNextFree = i+1;
242 }
243
244 lpTable->paEntries = newEntries;
245 lpTable->iEntries = newIEntries;
246
247 return 1;
248}
249
250/******************************************************************************
251 * alloc_handle
252 *
253 * Allocates a new handle to the specified object in a given handle table.
254 *
255 * PARAMS
256 * lpTable [I] Pointer to the handle table, from which the new handle is
257 * allocated.
258 * lpObject [I] Pointer to the object, for which a handle shall be allocated.
259 * lpHandle [O] Pointer to a handle variable, into which the handle value will
260 * be stored. If not successful, this will be
261 * INVALID_HANDLE_VALUE
262 * RETURNS
263 * non zero, if successful
264 * zero, if not successful (no free handle)
265 */
266static int alloc_handle(HANDLETBL *lpTable, OBJECTHDR *lpObject, HCRYPTKEY *lpHandle)
267{
268 int ret = 0;
269
270 TRACE("(lpTable=%p, lpObject=%p, lpHandle=%p)\n", lpTable, lpObject, lpHandle);
271
272 EnterCriticalSection(&lpTable->mutex);
273 if (lpTable->iFirstFree >= lpTable->iEntries)
274 if (!grow_handle_table(lpTable))
275 {
276 *lpHandle = (HCRYPTKEY)INVALID_HANDLE_VALUE;
277 goto exit;
278 }
279
280 *lpHandle = INDEX2HANDLE(lpTable->iFirstFree);
281
282 lpTable->paEntries[lpTable->iFirstFree].pObject = lpObject;
283 lpTable->iFirstFree = lpTable->paEntries[lpTable->iFirstFree].iNextFree;
284 InterlockedIncrement(&lpObject->refcount);
285
286 ret = 1;
287exit:
288 LeaveCriticalSection(&lpTable->mutex);
289 return ret;
290}
291
292/******************************************************************************
293 * release_handle
294 *
295 * Releases resources occupied by the specified handle in the given table.
296 * The reference count of the handled object is decremented. If it becomes
297 * zero and if the 'destructor' function pointer member is non NULL, the
298 * destructor function will be called. Note that release_handle does not
299 * release resources other than the handle itself. If this is wanted, do it
300 * in the destructor function.
301 *
302 * PARAMS
303 * lpTable [I] Pointer to the handle table, from which a handle is to be
304 * released.
305 * handle [I] The handle, which is to be released
306 * dwType [I] Identifier for the type of the object, for which a handle is
307 * to be released.
308 *
309 * RETURNS
310 * non zero, if successful
311 * zero, if not successful (invalid handle)
312 */
313int release_handle(HANDLETBL *lpTable, HCRYPTKEY handle, DWORD dwType)
314{
315 unsigned int index = HANDLE2INDEX(handle);
316 OBJECTHDR *pObject;
317 int ret = 0;
318
319 TRACE("(lpTable=%p, handle=%ld)\n", lpTable, handle);
320
321 EnterCriticalSection(&lpTable->mutex);
322
323 if (!is_valid_handle(lpTable, handle, dwType))
324 goto exit;
325
326 pObject = lpTable->paEntries[index].pObject;
327 if (InterlockedDecrement(&pObject->refcount) == 0)
328 {
329 TRACE("destroying handle %ld\n", handle);
330 if (pObject->destructor)
331 pObject->destructor(pObject);
332 }
333
334 lpTable->paEntries[index].pObject = NULL;
335 lpTable->paEntries[index].iNextFree = lpTable->iFirstFree;
336 lpTable->iFirstFree = index;
337
338 ret = 1;
339exit:
340 LeaveCriticalSection(&lpTable->mutex);
341 return ret;
342}
343
344/******************************************************************************
345 * lookup_handle
346 *
347 * Returns the object identified by the handle in the given handle table
348 *
349 * PARAMS
350 * lpTable [I] Pointer to the handle table, in which the handle is looked up.
351 * handle [I] The handle, which is to be looked up
352 * lplpObject [O] Pointer to the variable, into which the pointer to the
353 * object looked up is copied.
354 * RETURNS
355 * non zero, if successful
356 * zero, if not successful (invalid handle)
357 */
358int lookup_handle(HANDLETBL *lpTable, HCRYPTKEY handle, DWORD dwType, OBJECTHDR **lplpObject)
359{
360 int ret = 0;
361
362 TRACE("(lpTable=%p, handle=%ld, lplpObject=%p)\n", lpTable, handle, lplpObject);
363
364 EnterCriticalSection(&lpTable->mutex);
365 if (!is_valid_handle(lpTable, handle, dwType))
366 {
367 *lplpObject = NULL;
368 goto exit;
369 }
370 *lplpObject = lpTable->paEntries[HANDLE2INDEX(handle)].pObject;
371
372 ret = 1;
373exit:
374 LeaveCriticalSection(&lpTable->mutex);
375 return ret;
376}
377
378/******************************************************************************
379 * copy_handle
380 *
381 * Copies a handle. Increments the reference count of the object referenced
382 * by the handle.
383 *
384 * PARAMS
385 * lpTable [I] Pointer to the handle table, which holds the handle to be copied.
386 * handle [I] The handle to be copied.
387 * copy [O] Pointer to a handle variable, where the copied handle is put.
388 *
389 * RETURNS
390 * non zero, if successful
391 * zero, if not successful (invalid handle or out of memory)
392 */
393int copy_handle(HANDLETBL *lpTable, HCRYPTKEY handle, DWORD dwType, HCRYPTKEY *copy)
394{
395 OBJECTHDR *pObject;
396 int ret;
397
398 TRACE("(lpTable=%p, handle=%ld, copy=%p)\n", lpTable, handle, copy);
399
400 EnterCriticalSection(&lpTable->mutex);
401 if (!lookup_handle(lpTable, handle, dwType, &pObject))
402 {
403 *copy = (HCRYPTKEY)INVALID_HANDLE_VALUE;
404 LeaveCriticalSection(&lpTable->mutex);
405 return 0;
406 }
407
408 ret = alloc_handle(lpTable, pObject, copy);
409 LeaveCriticalSection(&lpTable->mutex);
410 return ret;
411}
412
413/******************************************************************************
414 * new_object
415 *
416 * Allocates a new object of size cbSize on the current process's heap.
417 * Initializes the object header using the destructor and dwType params.
418 * Allocates a handle to the object in the handle table pointed to by lpTable.
419 * Returns a pointer to the created object in ppObject.
420 * Returns a handle to the created object.
421 *
422 * PARAMS
423 * lpTable [I] Pointer to the handle table, from which a handle is to be
424 * allocated.
425 * cbSize [I] Size of the object to be allocated in bytes.
426 * dwType [I] Object type; will be copied to the object header.
427 * destructor [I] Function pointer to a destructor function. Will be called
428 * once the object's reference count gets zero.
429 * ppObject [O] Pointer to a pointer variable, where a pointer to the newly
430 * created object will be stored. You may set this to NULL.
431 *
432 * RETURNS
433 * INVALID_HANDLE_VALUE, if something went wrong.
434 * a handle to the new object, if successful.
435 */
436HCRYPTKEY new_object(HANDLETBL *lpTable, size_t cbSize, DWORD dwType, DESTRUCTOR destructor,
437 OBJECTHDR **ppObject)
438{
439 OBJECTHDR *pObject;
440 HCRYPTKEY hObject;
441
442 if (ppObject)
443 *ppObject = NULL;
444
445 pObject = HeapAlloc(GetProcessHeap(), 0, cbSize);
446 if (!pObject)
447 return (HCRYPTKEY)INVALID_HANDLE_VALUE;
448
449 pObject->dwType = dwType;
450 pObject->refcount = 0;
451 pObject->destructor = destructor;
452
453 if (!alloc_handle(lpTable, pObject, &hObject))
454 HeapFree(GetProcessHeap(), 0, pObject);
455 else
456 if (ppObject)
457 *ppObject = pObject;
458
459 return hObject;
460}
Note: See TracBrowser for help on using the repository browser.