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