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 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 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 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 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 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 */ 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 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