ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

handle.c
Go to the documentation of this file.
00001 /*
00002  * dlls/rsaenh/handle.c
00003  * Support code to manage HANDLE tables.
00004  *
00005  * Copyright 1998 Alexandre Julliard
00006  * Copyright 2002-2004 Mike McCormack for CodeWeavers
00007  * Copyright 2004 Michael Jung
00008  *
00009  * This library is free software; you can redistribute it and/or
00010  * modify it under the terms of the GNU Lesser General Public
00011  * License as published by the Free Software Foundation; either
00012  * version 2.1 of the License, or (at your option) any later version.
00013  *
00014  * This library is distributed in the hope that it will be useful,
00015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00017  * Lesser General Public License for more details.
00018  *
00019  * You should have received a copy of the GNU Lesser General Public
00020  * License along with this library; if not, write to the Free Software
00021  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00022  */
00023 
00024 #include <string.h>
00025 #include <stdarg.h>
00026 
00027 #include "windef.h"
00028 #include "winbase.h"
00029 #include "handle.h"
00030 
00031 #include "wine/debug.h"
00032 
00033 WINE_DEFAULT_DEBUG_CHANNEL(handle);
00034 
00035 #define HANDLE2INDEX(h) ((h)-1)
00036 #define INDEX2HANDLE(i) ((i)+1)
00037 
00038 /******************************************************************************
00039  *  init_handle_table
00040  *
00041  * Initializes the HANDLETABLE structure pointed to by lpTable
00042  *
00043  * PARAMS
00044  *  lpTable [I] Pointer to the HANDLETABLE structure, which is to be initialized.
00045  *
00046  * NOTES
00047  *  You have to call destroy_handle_table when you don't need the table
00048  *  any more.
00049  */
00050 void init_handle_table(struct handle_table *lpTable)
00051 {
00052     TRACE("(lpTable=%p)\n", lpTable);
00053         
00054     lpTable->paEntries = NULL;
00055     lpTable->iEntries = 0;
00056     lpTable->iFirstFree = 0;
00057     InitializeCriticalSection(&lpTable->mutex);
00058     lpTable->mutex.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": HANDLETABLE.mutex");
00059 }
00060 
00061 /******************************************************************************
00062  *  destroy_handle_table
00063  *
00064  * Destroys the handle table.
00065  * 
00066  * PARAMS
00067  *  lpTable [I] Pointer to the handle table, which is to be destroyed.
00068  */
00069 void destroy_handle_table(struct handle_table *lpTable)
00070 {
00071     TRACE("(lpTable=%p)\n", lpTable);
00072         
00073     HeapFree(GetProcessHeap(), 0, lpTable->paEntries);
00074     lpTable->mutex.DebugInfo->Spare[0] = 0;
00075     DeleteCriticalSection(&lpTable->mutex);
00076 }
00077 
00078 /******************************************************************************
00079  *  is_valid_handle
00080  *
00081  * Tests if handle is valid given the specified handle table
00082  * 
00083  * PARAMS
00084  *  lpTable [I] Pointer to the handle table, with respect to which the handle's 
00085  *              validness is tested.
00086  *  handle  [I] The handle tested for validness.
00087  *  dwType  [I] A magic value that identifies the referenced object's type.
00088  *
00089  * RETURNS
00090  *  non zero,  if handle is valid.
00091  *  zero,      if handle is not valid.
00092  */
00093 int is_valid_handle(struct handle_table *lpTable, HCRYPTKEY handle, DWORD dwType)
00094 {
00095     unsigned int index = HANDLE2INDEX(handle);
00096     int ret = 0;
00097 
00098     TRACE("(lpTable=%p, handle=%ld)\n", lpTable, handle);
00099     
00100     EnterCriticalSection(&lpTable->mutex);
00101         
00102     /* We don't use zero handle values */
00103     if (!handle) goto exit;
00104  
00105     /* Check for index out of table bounds */    
00106     if (index >= lpTable->iEntries) goto exit;
00107     
00108     /* Check if this handle is currently allocated */
00109     if (!lpTable->paEntries[index].pObject) goto exit;
00110     
00111     /* Check if this handle references an object of the correct type. */
00112     if (lpTable->paEntries[index].pObject->dwType != dwType) goto exit;
00113     
00114     ret = 1;
00115 exit:
00116     LeaveCriticalSection(&lpTable->mutex);
00117     return ret;
00118 }
00119 
00120 /******************************************************************************
00121  *  grow_handle_table [Internal]
00122  *
00123  * Grows the number of entries in the given table by TABLE_SIZE_INCREMENT
00124  *
00125  * PARAMS 
00126  *  lpTable [I] Pointer to the table, which is to be grown
00127  *
00128  * RETURNS
00129  *  non zero,  if successful
00130  *  zero,      if not successful (out of memory on process heap)
00131  *
00132  * NOTES
00133  *  This is a support function for alloc_handle. Do not call!
00134  */
00135 static int grow_handle_table(struct handle_table *lpTable) 
00136 {
00137     struct handle_table_entry *newEntries;
00138     unsigned int i, newIEntries;
00139 
00140     newIEntries = lpTable->iEntries + TABLE_SIZE_INCREMENT;
00141 
00142     newEntries = HeapAlloc(GetProcessHeap(), 0, sizeof(struct handle_table_entry)*newIEntries);
00143     if (!newEntries) 
00144         return 0;
00145 
00146     if (lpTable->paEntries)
00147     {
00148         memcpy(newEntries, lpTable->paEntries, sizeof(struct handle_table_entry)*lpTable->iEntries);
00149         HeapFree(GetProcessHeap(), 0, lpTable->paEntries);
00150     }
00151 
00152     for (i=lpTable->iEntries; i<newIEntries; i++)
00153     {
00154         newEntries[i].pObject = NULL;
00155         newEntries[i].iNextFree = i+1;
00156     }
00157 
00158     lpTable->paEntries = newEntries;
00159     lpTable->iEntries = newIEntries;
00160 
00161     return 1;
00162 }
00163 
00164 /******************************************************************************
00165  *  alloc_handle
00166  *
00167  * Allocates a new handle to the specified object in a given handle table.
00168  *
00169  * PARAMS
00170  *  lpTable  [I] Pointer to the handle table, from which the new handle is 
00171  *               allocated.
00172  *  lpObject [I] Pointer to the object, for which a handle shall be allocated.
00173  *  lpHandle [O] Pointer to a handle variable, into which the handle value will
00174  *               be stored. If not successful, this will be 
00175  *               INVALID_HANDLE_VALUE
00176  * RETURNS
00177  *  non zero,  if successful
00178  *  zero,      if not successful (no free handle)
00179  */
00180 static int alloc_handle(struct handle_table *lpTable, OBJECTHDR *lpObject, HCRYPTKEY *lpHandle)
00181 {
00182     int ret = 0;
00183 
00184     TRACE("(lpTable=%p, lpObject=%p, lpHandle=%p)\n", lpTable, lpObject, lpHandle);
00185         
00186     EnterCriticalSection(&lpTable->mutex);
00187     if (lpTable->iFirstFree >= lpTable->iEntries) 
00188         if (!grow_handle_table(lpTable))
00189         {
00190             *lpHandle = (HCRYPTKEY)INVALID_HANDLE_VALUE;
00191             goto exit;
00192         }
00193 
00194     *lpHandle = INDEX2HANDLE(lpTable->iFirstFree);
00195     
00196     lpTable->paEntries[lpTable->iFirstFree].pObject = lpObject;
00197     lpTable->iFirstFree = lpTable->paEntries[lpTable->iFirstFree].iNextFree;
00198     InterlockedIncrement(&lpObject->refcount);
00199 
00200     ret = 1;
00201 exit:
00202     LeaveCriticalSection(&lpTable->mutex);
00203     return ret;
00204 }
00205 
00206 /******************************************************************************
00207  *  release_handle
00208  *
00209  * Releases resources occupied by the specified handle in the given table.
00210  * The reference count of the handled object is decremented. If it becomes
00211  * zero and if the 'destructor' function pointer member is non NULL, the
00212  * destructor function will be called. Note that release_handle does not 
00213  * release resources other than the handle itself. If this is wanted, do it
00214  * in the destructor function.
00215  *
00216  * PARAMS
00217  *  lpTable [I] Pointer to the handle table, from which a handle is to be 
00218  *              released.
00219  *  handle  [I] The handle, which is to be released
00220  *  dwType  [I] Identifier for the type of the object, for which a handle is
00221  *              to be released.
00222  *
00223  * RETURNS
00224  *  non zero,  if successful
00225  *  zero,      if not successful (invalid handle)
00226  */
00227 int release_handle(struct handle_table *lpTable, HCRYPTKEY handle, DWORD dwType)
00228 {
00229     unsigned int index = HANDLE2INDEX(handle);
00230     OBJECTHDR *pObject;
00231     int ret = 0;
00232 
00233     TRACE("(lpTable=%p, handle=%ld)\n", lpTable, handle);
00234     
00235     EnterCriticalSection(&lpTable->mutex);
00236     
00237     if (!is_valid_handle(lpTable, handle, dwType))
00238         goto exit;
00239 
00240     pObject = lpTable->paEntries[index].pObject;
00241     if (InterlockedDecrement(&pObject->refcount) == 0)
00242     {
00243         TRACE("destroying handle %ld\n", handle);
00244         if (pObject->destructor)
00245             pObject->destructor(pObject);
00246     }
00247 
00248     lpTable->paEntries[index].pObject = NULL;
00249     lpTable->paEntries[index].iNextFree = lpTable->iFirstFree;
00250     lpTable->iFirstFree = index;
00251    
00252     ret = 1;
00253 exit:
00254     LeaveCriticalSection(&lpTable->mutex);
00255     return ret;
00256 }
00257 
00258 /******************************************************************************
00259  *  lookup_handle
00260  *
00261  * Returns the object identified by the handle in the given handle table
00262  *
00263  * PARAMS
00264  *  lpTable    [I] Pointer to the handle table, in which the handle is looked up.
00265  *  handle     [I] The handle, which is to be looked up
00266  *    lplpObject [O] Pointer to the variable, into which the pointer to the 
00267  *                   object looked up is copied.
00268  * RETURNS
00269  *  non zero,  if successful
00270  *  zero,      if not successful (invalid handle)
00271  */
00272 int lookup_handle(struct handle_table *lpTable, HCRYPTKEY handle, DWORD dwType, OBJECTHDR **lplpObject)
00273 {
00274     int ret = 0;
00275     
00276     TRACE("(lpTable=%p, handle=%ld, lplpObject=%p)\n", lpTable, handle, lplpObject);
00277     
00278     EnterCriticalSection(&lpTable->mutex);
00279     if (!is_valid_handle(lpTable, handle, dwType)) 
00280     {
00281         *lplpObject = NULL;
00282         goto exit;
00283     }
00284     *lplpObject = lpTable->paEntries[HANDLE2INDEX(handle)].pObject;
00285 
00286     ret = 1;
00287 exit:
00288     LeaveCriticalSection(&lpTable->mutex);
00289     return ret;
00290 }
00291 
00292 /******************************************************************************
00293  *  copy_handle
00294  *
00295  * Copies a handle. Increments the reference count of the object referenced
00296  * by the handle.
00297  *
00298  * PARAMS
00299  *  lpTable [I] Pointer to the handle table, which holds the handle to be copied.
00300  *  handle  [I] The handle to be copied.
00301  *  copy    [O] Pointer to a handle variable, where the copied handle is put.
00302  *
00303  * RETURNS
00304  *  non zero,  if successful
00305  *  zero,      if not successful (invalid handle or out of memory)
00306  */
00307 int copy_handle(struct handle_table *lpTable, HCRYPTKEY handle, DWORD dwType, HCRYPTKEY *copy)
00308 {
00309     OBJECTHDR *pObject;
00310     int ret;
00311         
00312     TRACE("(lpTable=%p, handle=%ld, copy=%p)\n", lpTable, handle, copy);
00313 
00314     EnterCriticalSection(&lpTable->mutex);
00315     if (!lookup_handle(lpTable, handle, dwType, &pObject)) 
00316     {
00317         *copy = (HCRYPTKEY)INVALID_HANDLE_VALUE;
00318         LeaveCriticalSection(&lpTable->mutex);
00319         return 0;
00320     }
00321 
00322     ret = alloc_handle(lpTable, pObject, copy);
00323     LeaveCriticalSection(&lpTable->mutex);
00324     return ret;
00325 }
00326 
00327 /******************************************************************************
00328  *  new_object
00329  *
00330  * Allocates a new object of size cbSize on the current process's heap.
00331  * Initializes the object header using the destructor and dwType params.
00332  * Allocates a handle to the object in the handle table pointed to by lpTable.
00333  * Returns a pointer to the created object in ppObject.
00334  * Returns a handle to the created object.
00335  *
00336  * PARAMS
00337  *  lpTable    [I] Pointer to the handle table, from which a handle is to be 
00338  *              allocated.
00339  *  cbSize     [I] Size of the object to be allocated in bytes.
00340  *  dwType     [I] Object type; will be copied to the object header.
00341  *  destructor [I] Function pointer to a destructor function. Will be called
00342  *                 once the object's reference count gets zero.
00343  *  ppObject   [O] Pointer to a pointer variable, where a pointer to the newly
00344  *                 created object will be stored. You may set this to NULL.
00345  *
00346  * RETURNS
00347  *  INVALID_HANDLE_VALUE,        if something went wrong.
00348  *  a handle to the new object,  if successful. 
00349  */
00350 HCRYPTKEY new_object(struct handle_table *lpTable, size_t cbSize, DWORD dwType, DESTRUCTOR destructor,
00351                         OBJECTHDR **ppObject)
00352 {
00353     OBJECTHDR *pObject;
00354     HCRYPTKEY hObject;
00355 
00356     if (ppObject)
00357         *ppObject = NULL;
00358 
00359     pObject = HeapAlloc(GetProcessHeap(), 0, cbSize);
00360     if (!pObject)
00361         return (HCRYPTKEY)INVALID_HANDLE_VALUE;
00362 
00363     pObject->dwType = dwType;
00364     pObject->refcount = 0;
00365     pObject->destructor = destructor;
00366 
00367     if (!alloc_handle(lpTable, pObject, &hObject))
00368         HeapFree(GetProcessHeap(), 0, pObject);
00369     else
00370         if (ppObject)
00371             *ppObject = pObject;
00372 
00373     return hObject;
00374 }

Generated on Sun May 27 2012 04:24:27 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.