2 * Copyright 2006 Juan Lang
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 #include "wine/debug.h"
24 #include "wine/list.h"
25 #include "crypt32_private.h"
27 WINE_DEFAULT_DEBUG_CHANNEL(context
);
29 #define CONTEXT_FROM_BASE_CONTEXT(p) (void*)(p+1)
30 #define BASE_CONTEXT_FROM_CONTEXT(p) ((BASE_CONTEXT*)(p)-1)
32 void *Context_CreateDataContext(size_t contextSize
, const context_vtbl_t
*vtbl
)
34 BASE_CONTEXT
*context
;
36 context
= CryptMemAlloc(contextSize
+ sizeof(BASE_CONTEXT
));
42 context
->linked
= NULL
;
43 context
->properties
= ContextPropertyList_Create();
44 if (!context
->properties
)
46 CryptMemFree(context
);
50 TRACE("returning %p\n", context
);
51 return CONTEXT_FROM_BASE_CONTEXT(context
);
54 void *Context_CreateLinkContext(unsigned int contextSize
, void *linked
, unsigned int extra
,
57 BASE_CONTEXT
*context
;
59 TRACE("(%d, %p, %d)\n", contextSize
, linked
, extra
);
61 context
= CryptMemAlloc(contextSize
+ sizeof(BASE_CONTEXT
) + extra
);
65 memcpy(CONTEXT_FROM_BASE_CONTEXT(context
), linked
, contextSize
);
66 context
->vtbl
= BASE_CONTEXT_FROM_CONTEXT(linked
)->vtbl
;
68 context
->linked
= BASE_CONTEXT_FROM_CONTEXT(linked
);
70 Context_AddRef(BASE_CONTEXT_FROM_CONTEXT(linked
));
72 TRACE("returning %p\n", context
);
73 return CONTEXT_FROM_BASE_CONTEXT(context
);
76 void Context_AddRef(context_t
*context
)
78 InterlockedIncrement(&context
->ref
);
79 TRACE("(%p) ref=%d\n", context
, context
->ref
);
82 void *Context_GetExtra(const void *context
, size_t contextSize
)
84 BASE_CONTEXT
*baseContext
= BASE_CONTEXT_FROM_CONTEXT(context
);
86 assert(baseContext
->linked
!= NULL
);
87 return (LPBYTE
)CONTEXT_FROM_BASE_CONTEXT(baseContext
) + contextSize
;
90 void *Context_GetLinkedContext(void *context
)
92 BASE_CONTEXT
*baseContext
= BASE_CONTEXT_FROM_CONTEXT(context
);
94 assert(baseContext
->linked
!= NULL
);
95 return CONTEXT_FROM_BASE_CONTEXT(baseContext
->linked
);
98 CONTEXT_PROPERTY_LIST
*Context_GetProperties(const void *context
)
100 BASE_CONTEXT
*ptr
= BASE_CONTEXT_FROM_CONTEXT(context
);
102 while (ptr
&& ptr
->linked
)
105 return ptr
->properties
;
108 BOOL
Context_Release(context_t
*context
)
112 if (context
->ref
<= 0)
114 ERR("%p's ref count is %d\n", context
, context
->ref
);
117 if (InterlockedDecrement(&context
->ref
) == 0)
119 TRACE("freeing %p\n", context
);
120 if (!context
->linked
)
122 ContextPropertyList_Free(context
->properties
);
123 context
->vtbl
->free(context
);
125 Context_Release(context
->linked
);
127 CryptMemFree(context
);
130 TRACE("%p's ref count is %d\n", context
, context
->ref
);
134 void Context_CopyProperties(const void *to
, const void *from
)
136 CONTEXT_PROPERTY_LIST
*toProperties
, *fromProperties
;
138 toProperties
= Context_GetProperties(to
);
139 fromProperties
= Context_GetProperties(from
);
140 assert(toProperties
&& fromProperties
);
141 ContextPropertyList_Copy(toProperties
, fromProperties
);
146 const WINE_CONTEXT_INTERFACE
*contextInterface
;
149 struct list contexts
;
152 struct ContextList
*ContextList_Create(
153 const WINE_CONTEXT_INTERFACE
*contextInterface
, size_t contextSize
)
155 struct ContextList
*list
= CryptMemAlloc(sizeof(struct ContextList
));
159 list
->contextInterface
= contextInterface
;
160 list
->contextSize
= contextSize
;
161 InitializeCriticalSection(&list
->cs
);
162 list
->cs
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": ContextList.cs");
163 list_init(&list
->contexts
);
168 static inline struct list
*ContextList_ContextToEntry(const struct ContextList
*list
,
174 ret
= Context_GetExtra(context
, list
->contextSize
);
180 static inline void *ContextList_EntryToContext(const struct ContextList
*list
,
183 return (LPBYTE
)entry
- list
->contextSize
;
186 void *ContextList_Add(struct ContextList
*list
, void *toLink
, void *toReplace
)
190 TRACE("(%p, %p, %p)\n", list
, toLink
, toReplace
);
192 context
= Context_CreateLinkContext(list
->contextSize
, toLink
,
193 sizeof(struct list
), TRUE
);
196 struct list
*entry
= ContextList_ContextToEntry(list
, context
);
198 TRACE("adding %p\n", context
);
199 EnterCriticalSection(&list
->cs
);
202 struct list
*existing
= ContextList_ContextToEntry(list
, toReplace
);
204 entry
->prev
= existing
->prev
;
205 entry
->next
= existing
->next
;
206 entry
->prev
->next
= entry
;
207 entry
->next
->prev
= entry
;
208 existing
->prev
= existing
->next
= existing
;
209 Context_Release(context_from_ptr(toReplace
));
212 list_add_head(&list
->contexts
, entry
);
213 LeaveCriticalSection(&list
->cs
);
218 void *ContextList_Enum(struct ContextList
*list
, void *pPrev
)
220 struct list
*listNext
;
223 EnterCriticalSection(&list
->cs
);
226 struct list
*prevEntry
= ContextList_ContextToEntry(list
, pPrev
);
228 listNext
= list_next(&list
->contexts
, prevEntry
);
229 Context_Release(context_from_ptr(pPrev
));
232 listNext
= list_next(&list
->contexts
, &list
->contexts
);
233 LeaveCriticalSection(&list
->cs
);
237 ret
= ContextList_EntryToContext(list
, listNext
);
238 Context_AddRef(context_from_ptr(ret
));
245 BOOL
ContextList_Remove(struct ContextList
*list
, void *context
)
247 struct list
*entry
= ContextList_ContextToEntry(list
, context
);
250 EnterCriticalSection(&list
->cs
);
251 if (!list_empty(entry
))
256 LeaveCriticalSection(&list
->cs
);
262 static void ContextList_Empty(struct ContextList
*list
)
264 struct list
*entry
, *next
;
266 EnterCriticalSection(&list
->cs
);
267 LIST_FOR_EACH_SAFE(entry
, next
, &list
->contexts
)
269 const void *context
= ContextList_EntryToContext(list
, entry
);
271 TRACE("removing %p\n", context
);
273 Context_Release(context_from_ptr(context
));
275 LeaveCriticalSection(&list
->cs
);
278 void ContextList_Free(struct ContextList
*list
)
280 ContextList_Empty(list
);
281 list
->cs
.DebugInfo
->Spare
[0] = 0;
282 DeleteCriticalSection(&list
->cs
);