Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenhandle.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
1.7.6.1
|