gdiplus: Get rid of no longer needed path and region fields.
[wine.git] / dlls / crypt32 / collectionstore.c
blobbfb83d1b99bcc732910f3d49bfe886709a19fe82
1 /*
2 * Copyright 2004-2007 Juan Lang
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.
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.
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
18 #include <stdarg.h>
19 #include "windef.h"
20 #include "winbase.h"
21 #include "wincrypt.h"
22 #include "wine/debug.h"
23 #include "crypt32_private.h"
25 WINE_DEFAULT_DEBUG_CHANNEL(crypt);
27 typedef struct _WINE_STORE_LIST_ENTRY
29 WINECRYPT_CERTSTORE *store;
30 DWORD dwUpdateFlags;
31 DWORD dwPriority;
32 struct list entry;
33 } WINE_STORE_LIST_ENTRY;
35 typedef struct _WINE_COLLECTIONSTORE
37 WINECRYPT_CERTSTORE hdr;
38 CRITICAL_SECTION cs;
39 struct list stores;
40 } WINE_COLLECTIONSTORE;
42 static void Collection_addref(WINECRYPT_CERTSTORE *store)
44 LONG ref = InterlockedIncrement(&store->ref);
45 TRACE("ref = %d\n", ref);
48 static DWORD Collection_release(WINECRYPT_CERTSTORE *store, DWORD flags)
50 WINE_COLLECTIONSTORE *cs = (WINE_COLLECTIONSTORE*)store;
51 WINE_STORE_LIST_ENTRY *entry, *next;
52 LONG ref;
54 if(flags)
55 FIXME("Unimplemented flags %x\n", flags);
57 ref = InterlockedDecrement(&cs->hdr.ref);
58 TRACE("(%p) ref=%d\n", store, ref);
59 if(ref)
60 return ERROR_SUCCESS;
62 LIST_FOR_EACH_ENTRY_SAFE(entry, next, &cs->stores, WINE_STORE_LIST_ENTRY, entry)
64 TRACE("closing %p\n", entry);
65 entry->store->vtbl->release(entry->store, flags);
66 CryptMemFree(entry);
68 cs->cs.DebugInfo->Spare[0] = 0;
69 DeleteCriticalSection(&cs->cs);
70 CRYPT_FreeStore(store);
71 return ERROR_SUCCESS;
74 static void Collection_releaseContext(WINECRYPT_CERTSTORE *store, context_t *context)
76 /* We don't cache context links, so just free them. */
77 Context_Free(context);
80 static context_t *CRYPT_CollectionCreateContextFromChild(WINE_COLLECTIONSTORE *store,
81 WINE_STORE_LIST_ENTRY *storeEntry, context_t *child)
83 context_t *ret;
85 ret = child->vtbl->clone(child, &store->hdr, TRUE);
86 if (!ret)
87 return NULL;
89 ret->u.ptr = storeEntry;
90 return ret;
93 static BOOL CRYPT_CollectionAddContext(WINE_COLLECTIONSTORE *store,
94 unsigned int contextFuncsOffset, context_t *context, context_t *toReplace,
95 context_t **pChildContext)
97 BOOL ret;
98 context_t *childContext = NULL;
99 WINE_STORE_LIST_ENTRY *storeEntry = NULL;
101 TRACE("(%p, %d, %p, %p)\n", store, contextFuncsOffset, context, toReplace);
103 ret = FALSE;
104 if (toReplace)
106 context_t *existingLinked = toReplace->linked;
107 CONTEXT_FUNCS *contextFuncs;
109 storeEntry = toReplace->u.ptr;
110 contextFuncs = (CONTEXT_FUNCS*)((LPBYTE)storeEntry->store->vtbl +
111 contextFuncsOffset);
112 ret = contextFuncs->addContext(storeEntry->store, context,
113 existingLinked, &childContext, TRUE);
115 else
117 WINE_STORE_LIST_ENTRY *entry, *next;
119 EnterCriticalSection(&store->cs);
120 LIST_FOR_EACH_ENTRY_SAFE(entry, next, &store->stores, WINE_STORE_LIST_ENTRY, entry)
122 if (entry->dwUpdateFlags & CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG)
124 CONTEXT_FUNCS *contextFuncs = (CONTEXT_FUNCS*)(
125 (LPBYTE)entry->store->vtbl + contextFuncsOffset);
127 storeEntry = entry;
128 ret = contextFuncs->addContext(entry->store, context, NULL, &childContext, TRUE);
129 break;
132 LeaveCriticalSection(&store->cs);
133 if (!storeEntry)
134 SetLastError(E_ACCESSDENIED);
136 *pChildContext = childContext;
137 return ret;
140 /* Advances a collection enumeration by one context, if possible, where
141 * advancing means:
142 * - calling the current store's enumeration function once, and returning
143 * the enumerated context if one is returned
144 * - moving to the next store if the current store has no more items, and
145 * recursively calling itself to get the next item.
146 * Returns NULL if the collection contains no more items or on error.
147 * Assumes the collection store's lock is held.
149 static context_t *CRYPT_CollectionAdvanceEnum(WINE_COLLECTIONSTORE *store,
150 WINE_STORE_LIST_ENTRY *storeEntry, const CONTEXT_FUNCS *contextFuncs,
151 context_t *prev)
153 context_t *child, *ret;
154 struct list *storeNext = list_next(&store->stores, &storeEntry->entry);
156 TRACE("(%p, %p, %p)\n", store, storeEntry, prev);
158 if (prev)
160 /* Ref-counting funny business: "duplicate" (addref) the child, because
161 * the free(pPrev) below can cause the ref count to become negative.
163 child = prev->linked;
164 Context_AddRef(child);
165 child = contextFuncs->enumContext(storeEntry->store, child);
166 Context_Release(prev);
167 prev = NULL;
169 else
171 child = contextFuncs->enumContext(storeEntry->store, NULL);
173 if (child) {
174 ret = CRYPT_CollectionCreateContextFromChild(store, storeEntry, child);
175 Context_Release(child);
177 else
179 if (storeNext)
181 /* We always want the same function pointers (from certs, crls)
182 * in the next store, so use the same offset into the next store.
184 size_t offset = (const BYTE *)contextFuncs - (LPBYTE)storeEntry->store->vtbl;
185 WINE_STORE_LIST_ENTRY *storeNextEntry =
186 LIST_ENTRY(storeNext, WINE_STORE_LIST_ENTRY, entry);
187 CONTEXT_FUNCS *storeNextContexts =
188 (CONTEXT_FUNCS*)((LPBYTE)storeNextEntry->store->vtbl + offset);
190 ret = CRYPT_CollectionAdvanceEnum(store, storeNextEntry,
191 storeNextContexts, NULL);
193 else
195 SetLastError(CRYPT_E_NOT_FOUND);
196 ret = NULL;
199 TRACE("returning %p\n", ret);
200 return ret;
203 static BOOL Collection_addCert(WINECRYPT_CERTSTORE *store, context_t *cert,
204 context_t *toReplace, context_t **ppStoreContext, BOOL use_link)
206 BOOL ret;
207 context_t *childContext = NULL;
208 WINE_COLLECTIONSTORE *cs = (WINE_COLLECTIONSTORE*)store;
210 ret = CRYPT_CollectionAddContext(cs, offsetof(store_vtbl_t, certs),
211 cert, toReplace, &childContext);
212 if (ppStoreContext && childContext)
214 WINE_STORE_LIST_ENTRY *storeEntry = childContext->u.ptr;
215 cert_t *context = (cert_t*)CRYPT_CollectionCreateContextFromChild(cs, storeEntry,
216 childContext);
218 *ppStoreContext = &context->base;
220 if (childContext)
221 Context_Release(childContext);
222 return ret;
225 static context_t *Collection_enumCert(WINECRYPT_CERTSTORE *store, context_t *prev)
227 WINE_COLLECTIONSTORE *cs = (WINE_COLLECTIONSTORE*)store;
228 context_t *ret;
230 TRACE("(%p, %p)\n", store, prev);
232 EnterCriticalSection(&cs->cs);
233 if (prev)
235 WINE_STORE_LIST_ENTRY *storeEntry = prev->u.ptr;
237 ret = CRYPT_CollectionAdvanceEnum(cs, storeEntry,
238 &storeEntry->store->vtbl->certs, prev);
240 else
242 if (!list_empty(&cs->stores))
244 WINE_STORE_LIST_ENTRY *storeEntry = LIST_ENTRY(cs->stores.next,
245 WINE_STORE_LIST_ENTRY, entry);
247 ret = CRYPT_CollectionAdvanceEnum(cs, storeEntry,
248 &storeEntry->store->vtbl->certs, NULL);
250 else
252 SetLastError(CRYPT_E_NOT_FOUND);
253 ret = NULL;
256 LeaveCriticalSection(&cs->cs);
257 TRACE("returning %p\n", ret);
258 return ret;
261 static BOOL Collection_deleteCert(WINECRYPT_CERTSTORE *store, context_t *context)
263 cert_t *cert = (cert_t*)context;
264 cert_t *linked;
266 TRACE("(%p, %p)\n", store, cert);
268 linked = (cert_t*)context->linked;
269 return CertDeleteCertificateFromStore(&linked->ctx);
272 static BOOL Collection_addCRL(WINECRYPT_CERTSTORE *store, context_t *crl,
273 context_t *toReplace, context_t **ppStoreContext, BOOL use_link)
275 BOOL ret;
276 context_t *childContext = NULL;
277 WINE_COLLECTIONSTORE *cs = (WINE_COLLECTIONSTORE*)store;
279 ret = CRYPT_CollectionAddContext(cs, offsetof(store_vtbl_t, crls),
280 crl, toReplace, &childContext);
281 if (ppStoreContext && childContext)
283 WINE_STORE_LIST_ENTRY *storeEntry = childContext->u.ptr;
284 crl_t *context = (crl_t*)CRYPT_CollectionCreateContextFromChild(cs, storeEntry,
285 childContext);
287 *ppStoreContext = &context->base;
289 if (childContext)
290 Context_Release(childContext);
291 return ret;
294 static context_t *Collection_enumCRL(WINECRYPT_CERTSTORE *store, context_t *prev)
296 WINE_COLLECTIONSTORE *cs = (WINE_COLLECTIONSTORE*)store;
297 context_t *ret;
299 TRACE("(%p, %p)\n", store, prev);
301 EnterCriticalSection(&cs->cs);
302 if (prev)
304 WINE_STORE_LIST_ENTRY *storeEntry = prev->u.ptr;
306 ret = CRYPT_CollectionAdvanceEnum(cs, storeEntry,
307 &storeEntry->store->vtbl->crls, prev);
309 else
311 if (!list_empty(&cs->stores))
313 WINE_STORE_LIST_ENTRY *storeEntry = LIST_ENTRY(cs->stores.next,
314 WINE_STORE_LIST_ENTRY, entry);
316 ret = CRYPT_CollectionAdvanceEnum(cs, storeEntry,
317 &storeEntry->store->vtbl->crls, NULL);
319 else
321 SetLastError(CRYPT_E_NOT_FOUND);
322 ret = NULL;
325 LeaveCriticalSection(&cs->cs);
326 TRACE("returning %p\n", ret);
327 return ret;
330 static BOOL Collection_deleteCRL(WINECRYPT_CERTSTORE *store, context_t *context)
332 crl_t *crl = (crl_t*)context, *linked;
334 TRACE("(%p, %p)\n", store, crl);
336 linked = (crl_t*)context->linked;
337 return CertDeleteCRLFromStore(&linked->ctx);
340 static BOOL Collection_addCTL(WINECRYPT_CERTSTORE *store, context_t *ctl,
341 context_t *toReplace, context_t **ppStoreContext, BOOL use_link)
343 BOOL ret;
344 context_t *childContext = NULL;
345 WINE_COLLECTIONSTORE *cs = (WINE_COLLECTIONSTORE*)store;
347 ret = CRYPT_CollectionAddContext(cs, offsetof(store_vtbl_t, ctls),
348 ctl, toReplace, &childContext);
349 if (ppStoreContext && childContext)
351 WINE_STORE_LIST_ENTRY *storeEntry = childContext->u.ptr;
352 ctl_t *context = (ctl_t*)CRYPT_CollectionCreateContextFromChild(cs, storeEntry,
353 childContext);
355 *ppStoreContext = &context->base;
357 if (childContext)
358 Context_Release(childContext);
359 return ret;
362 static context_t *Collection_enumCTL(WINECRYPT_CERTSTORE *store, context_t *prev)
364 WINE_COLLECTIONSTORE *cs = (WINE_COLLECTIONSTORE*)store;
365 void *ret;
367 TRACE("(%p, %p)\n", store, prev);
369 EnterCriticalSection(&cs->cs);
370 if (prev)
372 WINE_STORE_LIST_ENTRY *storeEntry = prev->u.ptr;
374 ret = CRYPT_CollectionAdvanceEnum(cs, storeEntry,
375 &storeEntry->store->vtbl->ctls, prev);
377 else
379 if (!list_empty(&cs->stores))
381 WINE_STORE_LIST_ENTRY *storeEntry = LIST_ENTRY(cs->stores.next,
382 WINE_STORE_LIST_ENTRY, entry);
384 ret = CRYPT_CollectionAdvanceEnum(cs, storeEntry,
385 &storeEntry->store->vtbl->ctls, NULL);
387 else
389 SetLastError(CRYPT_E_NOT_FOUND);
390 ret = NULL;
393 LeaveCriticalSection(&cs->cs);
394 TRACE("returning %p\n", ret);
395 return ret;
398 static BOOL Collection_deleteCTL(WINECRYPT_CERTSTORE *store, context_t *context)
400 ctl_t *ctl = (ctl_t*)context, *linked;
402 TRACE("(%p, %p)\n", store, ctl);
404 linked = (ctl_t*)context->linked;
405 return CertDeleteCTLFromStore(&linked->ctx);
408 static BOOL Collection_control(WINECRYPT_CERTSTORE *cert_store, DWORD dwFlags,
409 DWORD dwCtrlType, void const *pvCtrlPara)
411 BOOL ret;
412 WINE_COLLECTIONSTORE *store = (WINE_COLLECTIONSTORE*)cert_store;
413 WINE_STORE_LIST_ENTRY *entry;
415 TRACE("(%p, %08x, %d, %p)\n", cert_store, dwFlags, dwCtrlType, pvCtrlPara);
417 if (!store)
418 return TRUE;
419 if (store->hdr.dwMagic != WINE_CRYPTCERTSTORE_MAGIC)
421 SetLastError(E_INVALIDARG);
422 return FALSE;
424 if (store->hdr.type != StoreTypeCollection)
426 SetLastError(E_INVALIDARG);
427 return FALSE;
430 ret = TRUE;
431 EnterCriticalSection(&store->cs);
432 LIST_FOR_EACH_ENTRY(entry, &store->stores, WINE_STORE_LIST_ENTRY, entry)
434 if (entry->store->vtbl->control)
436 ret = entry->store->vtbl->control(entry->store, dwFlags, dwCtrlType, pvCtrlPara);
437 if (!ret)
438 break;
441 LeaveCriticalSection(&store->cs);
442 return ret;
445 static const store_vtbl_t CollectionStoreVtbl = {
446 Collection_addref,
447 Collection_release,
448 Collection_releaseContext,
449 Collection_control,
451 Collection_addCert,
452 Collection_enumCert,
453 Collection_deleteCert
454 }, {
455 Collection_addCRL,
456 Collection_enumCRL,
457 Collection_deleteCRL
458 }, {
459 Collection_addCTL,
460 Collection_enumCTL,
461 Collection_deleteCTL
465 WINECRYPT_CERTSTORE *CRYPT_CollectionOpenStore(HCRYPTPROV hCryptProv,
466 DWORD dwFlags, const void *pvPara)
468 WINE_COLLECTIONSTORE *store;
470 if (dwFlags & CERT_STORE_DELETE_FLAG)
472 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
473 store = NULL;
475 else
477 store = CryptMemAlloc(sizeof(WINE_COLLECTIONSTORE));
478 if (store)
480 memset(store, 0, sizeof(WINE_COLLECTIONSTORE));
481 CRYPT_InitStore(&store->hdr, dwFlags, StoreTypeCollection, &CollectionStoreVtbl);
482 InitializeCriticalSection(&store->cs);
483 store->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": PWINE_COLLECTIONSTORE->cs");
484 list_init(&store->stores);
487 return (WINECRYPT_CERTSTORE*)store;
490 BOOL WINAPI CertAddStoreToCollection(HCERTSTORE hCollectionStore,
491 HCERTSTORE hSiblingStore, DWORD dwUpdateFlags, DWORD dwPriority)
493 WINE_COLLECTIONSTORE *collection = hCollectionStore;
494 WINECRYPT_CERTSTORE *sibling = hSiblingStore;
495 WINE_STORE_LIST_ENTRY *entry;
496 BOOL ret;
498 TRACE("(%p, %p, %08x, %d)\n", hCollectionStore, hSiblingStore,
499 dwUpdateFlags, dwPriority);
501 if (!collection || !sibling)
502 return TRUE;
503 if (collection->hdr.dwMagic != WINE_CRYPTCERTSTORE_MAGIC)
505 SetLastError(E_INVALIDARG);
506 return FALSE;
508 if (collection->hdr.type != StoreTypeCollection)
510 SetLastError(E_INVALIDARG);
511 return FALSE;
513 if (sibling->dwMagic != WINE_CRYPTCERTSTORE_MAGIC)
515 SetLastError(E_INVALIDARG);
516 return FALSE;
519 entry = CryptMemAlloc(sizeof(WINE_STORE_LIST_ENTRY));
520 if (entry)
522 InterlockedIncrement(&sibling->ref);
523 TRACE("sibling %p's ref count is %d\n", sibling, sibling->ref);
524 entry->store = sibling;
525 entry->dwUpdateFlags = dwUpdateFlags;
526 entry->dwPriority = dwPriority;
527 list_init(&entry->entry);
528 TRACE("%p: adding %p, priority %d\n", collection, entry, dwPriority);
529 EnterCriticalSection(&collection->cs);
530 if (dwPriority)
532 WINE_STORE_LIST_ENTRY *cursor;
533 BOOL added = FALSE;
535 LIST_FOR_EACH_ENTRY(cursor, &collection->stores,
536 WINE_STORE_LIST_ENTRY, entry)
538 if (cursor->dwPriority < dwPriority)
540 list_add_before(&cursor->entry, &entry->entry);
541 added = TRUE;
542 break;
545 if (!added)
546 list_add_tail(&collection->stores, &entry->entry);
548 else
549 list_add_tail(&collection->stores, &entry->entry);
550 LeaveCriticalSection(&collection->cs);
551 ret = TRUE;
553 else
554 ret = FALSE;
555 return ret;
558 void WINAPI CertRemoveStoreFromCollection(HCERTSTORE hCollectionStore,
559 HCERTSTORE hSiblingStore)
561 WINE_COLLECTIONSTORE *collection = hCollectionStore;
562 WINECRYPT_CERTSTORE *sibling = hSiblingStore;
563 WINE_STORE_LIST_ENTRY *store, *next;
565 TRACE("(%p, %p)\n", hCollectionStore, hSiblingStore);
567 if (!collection || !sibling)
568 return;
569 if (collection->hdr.dwMagic != WINE_CRYPTCERTSTORE_MAGIC)
571 SetLastError(E_INVALIDARG);
572 return;
574 if (collection->hdr.type != StoreTypeCollection)
575 return;
576 if (sibling->dwMagic != WINE_CRYPTCERTSTORE_MAGIC)
578 SetLastError(E_INVALIDARG);
579 return;
581 EnterCriticalSection(&collection->cs);
582 LIST_FOR_EACH_ENTRY_SAFE(store, next, &collection->stores,
583 WINE_STORE_LIST_ENTRY, entry)
585 if (store->store == sibling)
587 list_remove(&store->entry);
588 CertCloseStore(store->store, 0);
589 CryptMemFree(store);
590 break;
593 LeaveCriticalSection(&collection->cs);