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

context.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 doxygen 1.7.6.1

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