Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygencontext.c
Go to the documentation of this file.
00001 /* 00002 * Copyright 2006 Juan Lang 00003 * 00004 * This library is free software; you can redistribute it and/or 00005 * modify it under the terms of the GNU Lesser General Public 00006 * License as published by the Free Software Foundation; either 00007 * version 2.1 of the License, or (at your option) any later version. 00008 * 00009 * This library is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00012 * Lesser General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU Lesser General Public 00015 * License along with this library; if not, write to the Free Software 00016 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 00017 */ 00018 #include <assert.h> 00019 #include <stdarg.h> 00020 #include "windef.h" 00021 #include "winbase.h" 00022 #include "wincrypt.h" 00023 #include "wine/debug.h" 00024 #include "wine/list.h" 00025 #include "crypt32_private.h" 00026 00027 WINE_DEFAULT_DEBUG_CHANNEL(context); 00028 00029 typedef enum _ContextType { 00030 ContextTypeData, 00031 ContextTypeLink, 00032 } ContextType; 00033 00034 typedef struct _BASE_CONTEXT 00035 { 00036 LONG ref; 00037 ContextType type; 00038 } BASE_CONTEXT, *PBASE_CONTEXT; 00039 00040 typedef struct _DATA_CONTEXT 00041 { 00042 LONG ref; 00043 ContextType type; /* always ContextTypeData */ 00044 PCONTEXT_PROPERTY_LIST properties; 00045 } DATA_CONTEXT, *PDATA_CONTEXT; 00046 00047 typedef struct _LINK_CONTEXT 00048 { 00049 LONG ref; 00050 ContextType type; /* always ContextTypeLink */ 00051 PBASE_CONTEXT linked; 00052 } LINK_CONTEXT, *PLINK_CONTEXT; 00053 00054 #define CONTEXT_FROM_BASE_CONTEXT(p, s) ((LPBYTE)(p) - (s)) 00055 #define BASE_CONTEXT_FROM_CONTEXT(p, s) (PBASE_CONTEXT)((LPBYTE)(p) + (s)) 00056 00057 void *Context_CreateDataContext(size_t contextSize) 00058 { 00059 void *ret = CryptMemAlloc(contextSize + sizeof(DATA_CONTEXT)); 00060 00061 if (ret) 00062 { 00063 PDATA_CONTEXT context = (PDATA_CONTEXT)((LPBYTE)ret + contextSize); 00064 00065 context->ref = 1; 00066 context->type = ContextTypeData; 00067 context->properties = ContextPropertyList_Create(); 00068 if (!context->properties) 00069 { 00070 CryptMemFree(ret); 00071 ret = NULL; 00072 } 00073 } 00074 TRACE("returning %p\n", ret); 00075 return ret; 00076 } 00077 00078 void *Context_CreateLinkContext(unsigned int contextSize, void *linked, unsigned int extra, 00079 BOOL addRef) 00080 { 00081 void *context = CryptMemAlloc(contextSize + sizeof(LINK_CONTEXT) + extra); 00082 00083 TRACE("(%d, %p, %d)\n", contextSize, linked, extra); 00084 00085 if (context) 00086 { 00087 PLINK_CONTEXT linkContext = (PLINK_CONTEXT)BASE_CONTEXT_FROM_CONTEXT( 00088 context, contextSize); 00089 PBASE_CONTEXT linkedBase = BASE_CONTEXT_FROM_CONTEXT(linked, 00090 contextSize); 00091 00092 memcpy(context, linked, contextSize); 00093 linkContext->ref = 1; 00094 linkContext->type = ContextTypeLink; 00095 linkContext->linked = linkedBase; 00096 if (addRef) 00097 Context_AddRef(linked, contextSize); 00098 TRACE("%p's ref count is %d\n", context, linkContext->ref); 00099 } 00100 TRACE("returning %p\n", context); 00101 return context; 00102 } 00103 00104 void Context_AddRef(void *context, size_t contextSize) 00105 { 00106 PBASE_CONTEXT baseContext = BASE_CONTEXT_FROM_CONTEXT(context, contextSize); 00107 00108 InterlockedIncrement(&baseContext->ref); 00109 TRACE("%p's ref count is %d\n", context, baseContext->ref); 00110 if (baseContext->type == ContextTypeLink) 00111 { 00112 void *linkedContext = Context_GetLinkedContext(context, contextSize); 00113 PBASE_CONTEXT linkedBase = BASE_CONTEXT_FROM_CONTEXT(linkedContext, 00114 contextSize); 00115 00116 /* Add-ref the linked contexts too */ 00117 while (linkedContext && linkedBase->type == ContextTypeLink) 00118 { 00119 InterlockedIncrement(&linkedBase->ref); 00120 TRACE("%p's ref count is %d\n", linkedContext, linkedBase->ref); 00121 linkedContext = Context_GetLinkedContext(linkedContext, 00122 contextSize); 00123 if (linkedContext) 00124 linkedBase = BASE_CONTEXT_FROM_CONTEXT(linkedContext, 00125 contextSize); 00126 else 00127 linkedBase = NULL; 00128 } 00129 if (linkedContext) 00130 { 00131 /* It's not a link context, so it wasn't add-ref'ed in the while 00132 * loop, so add-ref it here. 00133 */ 00134 linkedBase = BASE_CONTEXT_FROM_CONTEXT(linkedContext, 00135 contextSize); 00136 InterlockedIncrement(&linkedBase->ref); 00137 TRACE("%p's ref count is %d\n", linkedContext, linkedBase->ref); 00138 } 00139 } 00140 } 00141 00142 void *Context_GetExtra(const void *context, size_t contextSize) 00143 { 00144 PBASE_CONTEXT baseContext = BASE_CONTEXT_FROM_CONTEXT(context, contextSize); 00145 00146 assert(baseContext->type == ContextTypeLink); 00147 return (LPBYTE)baseContext + sizeof(LINK_CONTEXT); 00148 } 00149 00150 void *Context_GetLinkedContext(void *context, size_t contextSize) 00151 { 00152 PBASE_CONTEXT baseContext = BASE_CONTEXT_FROM_CONTEXT(context, contextSize); 00153 00154 assert(baseContext->type == ContextTypeLink); 00155 return CONTEXT_FROM_BASE_CONTEXT(((PLINK_CONTEXT)baseContext)->linked, 00156 contextSize); 00157 } 00158 00159 PCONTEXT_PROPERTY_LIST Context_GetProperties(const void *context, size_t contextSize) 00160 { 00161 PBASE_CONTEXT ptr = BASE_CONTEXT_FROM_CONTEXT(context, contextSize); 00162 00163 while (ptr && ptr->type == ContextTypeLink) 00164 ptr = ((PLINK_CONTEXT)ptr)->linked; 00165 return (ptr && ptr->type == ContextTypeData) ? 00166 ((PDATA_CONTEXT)ptr)->properties : NULL; 00167 } 00168 00169 BOOL Context_Release(void *context, size_t contextSize, 00170 ContextFreeFunc dataContextFree) 00171 { 00172 PBASE_CONTEXT base = BASE_CONTEXT_FROM_CONTEXT(context, contextSize); 00173 BOOL ret = TRUE; 00174 00175 if (base->ref <= 0) 00176 { 00177 ERR("%p's ref count is %d\n", context, base->ref); 00178 return FALSE; 00179 } 00180 if (base->type == ContextTypeLink) 00181 { 00182 /* The linked context is of the same type as this, so release 00183 * it as well, using the same offset and data free function. 00184 */ 00185 ret = Context_Release(CONTEXT_FROM_BASE_CONTEXT( 00186 ((PLINK_CONTEXT)base)->linked, contextSize), contextSize, 00187 dataContextFree); 00188 } 00189 if (InterlockedDecrement(&base->ref) == 0) 00190 { 00191 TRACE("freeing %p\n", context); 00192 if (base->type == ContextTypeData) 00193 { 00194 ContextPropertyList_Free(((PDATA_CONTEXT)base)->properties); 00195 dataContextFree(context); 00196 } 00197 CryptMemFree(context); 00198 } 00199 else 00200 TRACE("%p's ref count is %d\n", context, base->ref); 00201 return ret; 00202 } 00203 00204 void Context_CopyProperties(const void *to, const void *from, 00205 size_t contextSize) 00206 { 00207 PCONTEXT_PROPERTY_LIST toProperties, fromProperties; 00208 00209 toProperties = Context_GetProperties(to, contextSize); 00210 fromProperties = Context_GetProperties(from, contextSize); 00211 assert(toProperties && fromProperties); 00212 ContextPropertyList_Copy(toProperties, fromProperties); 00213 } 00214 00215 struct ContextList 00216 { 00217 PCWINE_CONTEXT_INTERFACE contextInterface; 00218 size_t contextSize; 00219 CRITICAL_SECTION cs; 00220 struct list contexts; 00221 }; 00222 00223 struct ContextList *ContextList_Create( 00224 PCWINE_CONTEXT_INTERFACE contextInterface, size_t contextSize) 00225 { 00226 struct ContextList *list = CryptMemAlloc(sizeof(struct ContextList)); 00227 00228 if (list) 00229 { 00230 list->contextInterface = contextInterface; 00231 list->contextSize = contextSize; 00232 InitializeCriticalSection(&list->cs); 00233 list->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": ContextList.cs"); 00234 list_init(&list->contexts); 00235 } 00236 return list; 00237 } 00238 00239 static inline struct list *ContextList_ContextToEntry(const struct ContextList *list, 00240 const void *context) 00241 { 00242 struct list *ret; 00243 00244 if (context) 00245 ret = Context_GetExtra(context, list->contextSize); 00246 else 00247 ret = NULL; 00248 return ret; 00249 } 00250 00251 static inline void *ContextList_EntryToContext(const struct ContextList *list, 00252 struct list *entry) 00253 { 00254 return (LPBYTE)entry - sizeof(LINK_CONTEXT) - list->contextSize; 00255 } 00256 00257 void *ContextList_Add(struct ContextList *list, void *toLink, void *toReplace) 00258 { 00259 void *context; 00260 00261 TRACE("(%p, %p, %p)\n", list, toLink, toReplace); 00262 00263 context = Context_CreateLinkContext(list->contextSize, toLink, 00264 sizeof(struct list), TRUE); 00265 if (context) 00266 { 00267 struct list *entry = ContextList_ContextToEntry(list, context); 00268 00269 TRACE("adding %p\n", context); 00270 EnterCriticalSection(&list->cs); 00271 if (toReplace) 00272 { 00273 struct list *existing = ContextList_ContextToEntry(list, toReplace); 00274 00275 entry->prev = existing->prev; 00276 entry->next = existing->next; 00277 entry->prev->next = entry; 00278 entry->next->prev = entry; 00279 existing->prev = existing->next = existing; 00280 list->contextInterface->free(toReplace); 00281 } 00282 else 00283 list_add_head(&list->contexts, entry); 00284 LeaveCriticalSection(&list->cs); 00285 } 00286 return context; 00287 } 00288 00289 void *ContextList_Enum(struct ContextList *list, void *pPrev) 00290 { 00291 struct list *listNext; 00292 void *ret; 00293 00294 EnterCriticalSection(&list->cs); 00295 if (pPrev) 00296 { 00297 struct list *prevEntry = ContextList_ContextToEntry(list, pPrev); 00298 00299 listNext = list_next(&list->contexts, prevEntry); 00300 list->contextInterface->free(pPrev); 00301 } 00302 else 00303 listNext = list_next(&list->contexts, &list->contexts); 00304 LeaveCriticalSection(&list->cs); 00305 00306 if (listNext) 00307 { 00308 ret = ContextList_EntryToContext(list, listNext); 00309 list->contextInterface->duplicate(ret); 00310 } 00311 else 00312 ret = NULL; 00313 return ret; 00314 } 00315 00316 BOOL ContextList_Remove(struct ContextList *list, void *context) 00317 { 00318 struct list *entry = ContextList_ContextToEntry(list, context); 00319 BOOL inList = FALSE; 00320 00321 EnterCriticalSection(&list->cs); 00322 if (!list_empty(entry)) 00323 { 00324 list_remove(entry); 00325 inList = TRUE; 00326 } 00327 LeaveCriticalSection(&list->cs); 00328 if (inList) 00329 list_init(entry); 00330 return inList; 00331 } 00332 00333 static void ContextList_Empty(struct ContextList *list) 00334 { 00335 struct list *entry, *next; 00336 00337 EnterCriticalSection(&list->cs); 00338 LIST_FOR_EACH_SAFE(entry, next, &list->contexts) 00339 { 00340 const void *context = ContextList_EntryToContext(list, entry); 00341 00342 TRACE("removing %p\n", context); 00343 list_remove(entry); 00344 list->contextInterface->free(context); 00345 } 00346 LeaveCriticalSection(&list->cs); 00347 } 00348 00349 void ContextList_Free(struct ContextList *list) 00350 { 00351 ContextList_Empty(list); 00352 list->cs.DebugInfo->Spare[0] = 0; 00353 DeleteCriticalSection(&list->cs); 00354 CryptMemFree(list); 00355 } Generated on Fri May 25 2012 04:18:17 for ReactOS by
1.7.6.1
|