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