wininet: Remove the custom thread pool implementation and use QueueUserWorkItem instead.
[wine] / dlls / crypt32 / proplist.c
1 /*
2  * Copyright 2004-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 "wincrypt.h"
23 #include "wine/debug.h"
24 #include "wine/list.h"
25 #include "crypt32_private.h"
26
27 WINE_DEFAULT_DEBUG_CHANNEL(crypt);
28
29 typedef struct _CONTEXT_PROPERTY_LIST
30 {
31     CRITICAL_SECTION cs;
32     struct list      properties;
33 } CONTEXT_PROPERTY_LIST;
34
35 typedef struct _CONTEXT_PROPERTY
36 {
37     DWORD       propID;
38     DWORD       cbData;
39     LPBYTE      pbData;
40     struct list entry;
41 } CONTEXT_PROPERTY, *PCONTEXT_PROPERTY;
42
43 PCONTEXT_PROPERTY_LIST ContextPropertyList_Create(void)
44 {
45     PCONTEXT_PROPERTY_LIST list = CryptMemAlloc(sizeof(CONTEXT_PROPERTY_LIST));
46
47     if (list)
48     {
49         InitializeCriticalSection(&list->cs);
50         list_init(&list->properties);
51     }
52     return list;
53 }
54
55 void ContextPropertyList_Free(PCONTEXT_PROPERTY_LIST list)
56 {
57     PCONTEXT_PROPERTY prop, next;
58
59     LIST_FOR_EACH_ENTRY_SAFE(prop, next, &list->properties, CONTEXT_PROPERTY,
60      entry)
61     {
62         list_remove(&prop->entry);
63         CryptMemFree(prop->pbData);
64         CryptMemFree(prop);
65     }
66     DeleteCriticalSection(&list->cs);
67     CryptMemFree(list);
68 }
69
70 BOOL ContextPropertyList_FindProperty(PCONTEXT_PROPERTY_LIST list, DWORD id,
71  PCRYPT_DATA_BLOB blob)
72 {
73     PCONTEXT_PROPERTY prop;
74     BOOL ret = FALSE;
75
76     TRACE("(%p, %d, %p)\n", list, id, blob);
77
78     EnterCriticalSection(&list->cs);
79     LIST_FOR_EACH_ENTRY(prop, &list->properties, CONTEXT_PROPERTY, entry)
80     {
81         if (prop->propID == id)
82         {
83             blob->cbData = prop->cbData;
84             blob->pbData = prop->pbData;
85             ret = TRUE;
86             break;
87         }
88     }
89     LeaveCriticalSection(&list->cs);
90     return ret;
91 }
92
93 BOOL ContextPropertyList_SetProperty(PCONTEXT_PROPERTY_LIST list, DWORD id,
94  const BYTE *pbData, size_t cbData)
95 {
96     LPBYTE data;
97     BOOL ret = FALSE;
98
99     if (cbData)
100     {
101         data = CryptMemAlloc(cbData);
102         if (data)
103             memcpy(data, pbData, cbData);
104     }
105     else
106         data = NULL;
107     if (!cbData || data)
108     {
109         PCONTEXT_PROPERTY prop;
110         BOOL found = FALSE;
111
112         EnterCriticalSection(&list->cs);
113         LIST_FOR_EACH_ENTRY(prop, &list->properties, CONTEXT_PROPERTY, entry)
114         {
115             if (prop->propID == id)
116             {
117                 found = TRUE;
118                 break;
119             }
120         }
121         if (found)
122         {
123             CryptMemFree(prop->pbData);
124             prop->cbData = cbData;
125             prop->pbData = data;
126             ret = TRUE;
127         }
128         else
129         {
130             prop = CryptMemAlloc(sizeof(CONTEXT_PROPERTY));
131             if (prop)
132             {
133                 prop->propID = id;
134                 prop->cbData = cbData;
135                 prop->pbData = data;
136                 list_add_tail(&list->properties, &prop->entry);
137                 ret = TRUE;
138             }
139             else
140                 CryptMemFree(data);
141         }
142         LeaveCriticalSection(&list->cs);
143     }
144     return ret;
145 }
146
147 void ContextPropertyList_RemoveProperty(PCONTEXT_PROPERTY_LIST list, DWORD id)
148 {
149     PCONTEXT_PROPERTY prop, next;
150
151     EnterCriticalSection(&list->cs);
152     LIST_FOR_EACH_ENTRY_SAFE(prop, next, &list->properties, CONTEXT_PROPERTY,
153      entry)
154     {
155         if (prop->propID == id)
156         {
157             list_remove(&prop->entry);
158             CryptMemFree(prop->pbData);
159             CryptMemFree(prop);
160             break;
161         }
162     }
163     LeaveCriticalSection(&list->cs);
164 }
165
166 /* Since the properties are stored in a list, this is a tad inefficient
167  * (O(n^2)) since I have to find the previous position every time.
168  */
169 DWORD ContextPropertyList_EnumPropIDs(PCONTEXT_PROPERTY_LIST list, DWORD id)
170 {
171     DWORD ret;
172
173     EnterCriticalSection(&list->cs);
174     if (id)
175     {
176         PCONTEXT_PROPERTY cursor = NULL;
177
178         LIST_FOR_EACH_ENTRY(cursor, &list->properties, CONTEXT_PROPERTY, entry)
179         {
180             if (cursor->propID == id)
181                 break;
182         }
183         if (cursor)
184         {
185             if (cursor->entry.next != &list->properties)
186                 ret = LIST_ENTRY(cursor->entry.next, CONTEXT_PROPERTY,
187                  entry)->propID;
188             else
189                 ret = 0;
190         }
191         else
192             ret = 0;
193     }
194     else if (!list_empty(&list->properties))
195         ret = LIST_ENTRY(list->properties.next, CONTEXT_PROPERTY,
196          entry)->propID;
197     else
198         ret = 0;
199     LeaveCriticalSection(&list->cs);
200     return ret;
201 }
202
203 void ContextPropertyList_Copy(PCONTEXT_PROPERTY_LIST to,
204  PCONTEXT_PROPERTY_LIST from)
205 {
206     PCONTEXT_PROPERTY prop;
207
208     EnterCriticalSection(&from->cs);
209     LIST_FOR_EACH_ENTRY(prop, &from->properties, CONTEXT_PROPERTY, entry)
210     {
211         ContextPropertyList_SetProperty(to, prop->propID, prop->pbData,
212          prop->cbData);
213     }
214     LeaveCriticalSection(&from->cs);
215 }