source: trunk/src/crypt32/context.c

Last change on this file was 22020, checked in by dmik, 13 years ago

Disable debug fields of RTL_CRITICAL_SECTION_DEBUG.

Odin uses the DebugInfo ptr in CRITICAL_SECTION for its own purposes
which are incompatible with NT. For this reason any NT-style usage must
be disabled.

This in particular fixes debug assertions and crashes in CRYPT32.DLL (due to
misinterpretation of the structure fields) which happened e.g. during playback of
some Flash content.

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