source: trunk/src/crypt32/context.c@ 21311

Last change on this file since 21311 was 21311, checked in by vladest, 16 years ago

Added CRYPT32 and MSCMS APIs support

File size: 8.9 KB
Line 
1/*
2 * Copyright 2006 Juan Lang
3 *
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.
8 *
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.
13 *
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
17 */
18#include <assert.h>
19#include <stdarg.h>
20#include "windef.h"
21#include "winbase.h"
22#include "winerror.h"
23#include "wincrypt.h"
24#include "wine/debug.h"
25#include "wine/list.h"
26#include "crypt32_private.h"
27
28WINE_DEFAULT_DEBUG_CHANNEL(crypt);
29
30typedef enum _ContextType {
31 ContextTypeData,
32 ContextTypeLink,
33} ContextType;
34
35typedef struct _BASE_CONTEXT
36{
37 LONG ref;
38 ContextType type;
39} BASE_CONTEXT, *PBASE_CONTEXT;
40
41typedef struct _DATA_CONTEXT
42{
43 LONG ref;
44 ContextType type; /* always ContextTypeData */
45 PCONTEXT_PROPERTY_LIST properties;
46} DATA_CONTEXT, *PDATA_CONTEXT;
47
48typedef struct _LINK_CONTEXT
49{
50 LONG ref;
51 ContextType type; /* always ContextTypeLink */
52 PBASE_CONTEXT linked;
53} LINK_CONTEXT, *PLINK_CONTEXT;
54
55#define CONTEXT_FROM_BASE_CONTEXT(p, s) ((LPBYTE)(p) - (s))
56#define BASE_CONTEXT_FROM_CONTEXT(p, s) (PBASE_CONTEXT)((LPBYTE)(p) + (s))
57
58void *Context_CreateDataContext(size_t contextSize)
59{
60 void *ret = CryptMemAlloc(contextSize + sizeof(DATA_CONTEXT));
61
62 if (ret)
63 {
64 PDATA_CONTEXT context = (PDATA_CONTEXT)((LPBYTE)ret + contextSize);
65
66 context->ref = 1;
67 context->type = ContextTypeData;
68 context->properties = ContextPropertyList_Create();
69 if (!context->properties)
70 {
71 CryptMemFree(ret);
72 ret = NULL;
73 }
74 }
75 TRACE("returning %p\n", ret);
76 return ret;
77}
78
79void *Context_CreateLinkContext(unsigned int contextSize, void *linked, unsigned int extra,
80 BOOL addRef)
81{
82 void *context = CryptMemAlloc(contextSize + sizeof(LINK_CONTEXT) + extra);
83
84 TRACE("(%d, %p, %d)\n", contextSize, linked, extra);
85
86 if (context)
87 {
88 PLINK_CONTEXT linkContext = (PLINK_CONTEXT)BASE_CONTEXT_FROM_CONTEXT(
89 context, contextSize);
90 PBASE_CONTEXT linkedBase = BASE_CONTEXT_FROM_CONTEXT(linked,
91 contextSize);
92
93 memcpy(context, linked, contextSize);
94 linkContext->ref = 1;
95 linkContext->type = ContextTypeLink;
96 linkContext->linked = linkedBase;
97 if (addRef)
98 InterlockedIncrement(&linkedBase->ref);
99 TRACE("%p's ref count is %d\n", context, linkContext->ref);
100 }
101 TRACE("returning %p\n", context);
102 return context;
103}
104
105void Context_AddRef(void *context, size_t contextSize)
106{
107 PBASE_CONTEXT baseContext = BASE_CONTEXT_FROM_CONTEXT(context, contextSize);
108
109 InterlockedIncrement(&baseContext->ref);
110}
111
112void *Context_GetExtra(const void *context, size_t contextSize)
113{
114 PBASE_CONTEXT baseContext = BASE_CONTEXT_FROM_CONTEXT(context, contextSize);
115
116 assert(baseContext->type == ContextTypeLink);
117 return (LPBYTE)baseContext + sizeof(LINK_CONTEXT);
118}
119
120void *Context_GetLinkedContext(void *context, size_t contextSize)
121{
122 PBASE_CONTEXT baseContext = BASE_CONTEXT_FROM_CONTEXT(context, contextSize);
123
124 assert(baseContext->type == ContextTypeLink);
125 return CONTEXT_FROM_BASE_CONTEXT(((PLINK_CONTEXT)baseContext)->linked,
126 contextSize);
127}
128
129PCONTEXT_PROPERTY_LIST Context_GetProperties(const void *context, size_t contextSize)
130{
131 PBASE_CONTEXT ptr = BASE_CONTEXT_FROM_CONTEXT(context, contextSize);
132
133 while (ptr && ptr->type == ContextTypeLink)
134 ptr = ((PLINK_CONTEXT)ptr)->linked;
135 return (ptr && ptr->type == ContextTypeData) ?
136 ((PDATA_CONTEXT)ptr)->properties : NULL;
137}
138
139void Context_Release(void *context, size_t contextSize,
140 ContextFreeFunc dataContextFree)
141{
142 PBASE_CONTEXT base = BASE_CONTEXT_FROM_CONTEXT(context, contextSize);
143
144 if (InterlockedDecrement(&base->ref) == 0)
145 {
146 TRACE("freeing %p\n", context);
147 switch (base->type)
148 {
149 case ContextTypeData:
150 ContextPropertyList_Free(((PDATA_CONTEXT)base)->properties);
151 dataContextFree(context);
152 break;
153 case ContextTypeLink:
154 /* The linked context is of the same type as this, so release
155 * it as well, using the same offset and data free function.
156 */
157 Context_Release(CONTEXT_FROM_BASE_CONTEXT(
158 ((PLINK_CONTEXT)base)->linked, contextSize), contextSize,
159 dataContextFree);
160 break;
161 default:
162 assert(0);
163 }
164 CryptMemFree(context);
165 }
166 else
167 TRACE("%p's ref count is %d\n", context, base->ref);
168}
169
170void Context_CopyProperties(const void *to, const void *from,
171 size_t contextSize)
172{
173 PCONTEXT_PROPERTY_LIST toProperties, fromProperties;
174
175 toProperties = Context_GetProperties((void *)to, contextSize);
176 fromProperties = Context_GetProperties((void *)from, contextSize);
177 assert(toProperties && fromProperties);
178 ContextPropertyList_Copy(toProperties, fromProperties);
179}
180
181struct ContextList
182{
183 PCWINE_CONTEXT_INTERFACE contextInterface;
184 size_t contextSize;
185 RTL_CRITICAL_SECTION cs;
186 struct list contexts;
187};
188
189struct ContextList *ContextList_Create(
190 PCWINE_CONTEXT_INTERFACE contextInterface, size_t contextSize)
191{
192 struct ContextList *list = CryptMemAlloc(sizeof(struct ContextList));
193
194 if (list)
195 {
196 list->contextInterface = contextInterface;
197 list->contextSize = contextSize;
198 InitializeCriticalSection(&list->cs);
199 list->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": ContextList.cs");
200 list_init(&list->contexts);
201 }
202 return list;
203}
204
205static inline struct list *ContextList_ContextToEntry(struct ContextList *list,
206 const void *context)
207{
208 struct list *ret;
209
210 if (context)
211 ret = Context_GetExtra(context, list->contextSize);
212 else
213 ret = NULL;
214 return ret;
215}
216
217static inline void *ContextList_EntryToContext(struct ContextList *list,
218 struct list *entry)
219{
220 return (LPBYTE)entry - sizeof(LINK_CONTEXT) - list->contextSize;
221}
222
223void *ContextList_Add(struct ContextList *list, void *toLink, void *toReplace)
224{
225 void *context;
226
227 TRACE("(%p, %p, %p)\n", list, toLink, toReplace);
228
229 context = Context_CreateLinkContext(list->contextSize, toLink,
230 sizeof(struct list), TRUE);
231 if (context)
232 {
233 struct list *entry = ContextList_ContextToEntry(list, context);
234
235 TRACE("adding %p\n", context);
236 EnterCriticalSection(&list->cs);
237 if (toReplace)
238 {
239 struct list *existing = ContextList_ContextToEntry(list, toReplace);
240
241 entry->prev = existing->prev;
242 entry->next = existing->next;
243 entry->prev->next = entry;
244 entry->next->prev = entry;
245 existing->prev = existing->next = existing;
246 list->contextInterface->confree(toReplace);
247 }
248 else
249 list_add_head(&list->contexts, entry);
250 LeaveCriticalSection(&list->cs);
251 }
252 return context;
253}
254
255void *ContextList_Enum(struct ContextList *list, void *pPrev)
256{
257 struct list *listNext;
258 void *ret;
259
260 EnterCriticalSection(&list->cs);
261 if (pPrev)
262 {
263 struct list *prevEntry = ContextList_ContextToEntry(list, pPrev);
264
265 listNext = list_next(&list->contexts, prevEntry);
266 list->contextInterface->confree(pPrev);
267 }
268 else
269 listNext = list_next(&list->contexts, &list->contexts);
270 LeaveCriticalSection(&list->cs);
271
272 if (listNext)
273 {
274 ret = ContextList_EntryToContext(list, listNext);
275 list->contextInterface->duplicate(ret);
276 }
277 else
278 ret = NULL;
279 return ret;
280}
281
282void ContextList_Delete(struct ContextList *list, void *context)
283{
284 struct list *entry = ContextList_ContextToEntry(list, context);
285
286 EnterCriticalSection(&list->cs);
287 list_remove(entry);
288 LeaveCriticalSection(&list->cs);
289 list->contextInterface->confree(context);
290}
291
292void ContextList_Empty(struct ContextList *list)
293{
294 struct list *entry, *next;
295
296 EnterCriticalSection(&list->cs);
297 LIST_FOR_EACH_SAFE(entry, next, &list->contexts)
298 {
299 const void *context = ContextList_EntryToContext(list, entry);
300
301 TRACE("removing %p\n", context);
302 list_remove(entry);
303 list->contextInterface->confree(context);
304 }
305 LeaveCriticalSection(&list->cs);
306}
307
308void ContextList_Free(struct ContextList *list)
309{
310 ContextList_Empty(list);
311 list->cs.DebugInfo->Spare[0] = 0;
312 DeleteCriticalSection(&list->cs);
313 CryptMemFree(list);
314}
Note: See TracBrowser for help on using the repository browser.