From 9f85156e23c808bc8beff9f32dbfdf2dc7280116 Mon Sep 17 00:00:00 2001 From: Juan Lang Date: Thu, 16 Aug 2007 10:49:33 -0700 Subject: [PATCH] crypt32: Move collection stores to a separate file. --- dlls/crypt32/Makefile.in | 7 +- dlls/crypt32/collectionstore.c | 481 +++++++++++++++++++++++++++++++++ dlls/crypt32/crypt32_private.h | 7 + dlls/crypt32/store.c | 459 +------------------------------ 4 files changed, 494 insertions(+), 460 deletions(-) create mode 100644 dlls/crypt32/collectionstore.c diff --git a/dlls/crypt32/Makefile.in b/dlls/crypt32/Makefile.in index e065c4090ed..9dfe832c332 100644 --- a/dlls/crypt32/Makefile.in +++ b/dlls/crypt32/Makefile.in @@ -11,10 +11,12 @@ C_SRCS = \ base64.c \ cert.c \ chain.c \ - crl.c \ + collectionstore.c \ context.c \ + crl.c \ decode.c \ encode.c \ + main.c \ msg.c \ oid.c \ proplist.c \ @@ -22,8 +24,7 @@ C_SRCS = \ serialize.c \ sip.c \ store.c \ - str.c \ - main.c + str.c RC_SRCS = crypt32.rc diff --git a/dlls/crypt32/collectionstore.c b/dlls/crypt32/collectionstore.c new file mode 100644 index 00000000000..e4123375aab --- /dev/null +++ b/dlls/crypt32/collectionstore.c @@ -0,0 +1,481 @@ +/* + * Copyright 2004-2007 Juan Lang + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ +#include +#include "windef.h" +#include "winbase.h" +#include "wincrypt.h" +#include "wine/debug.h" +#include "wine/list.h" +#include "crypt32_private.h" + +WINE_DEFAULT_DEBUG_CHANNEL(crypt); + +typedef struct _WINE_STORE_LIST_ENTRY +{ + PWINECRYPT_CERTSTORE store; + DWORD dwUpdateFlags; + DWORD dwPriority; + struct list entry; +} WINE_STORE_LIST_ENTRY, *PWINE_STORE_LIST_ENTRY; + +typedef struct _WINE_COLLECTIONSTORE +{ + WINECRYPT_CERTSTORE hdr; + CRITICAL_SECTION cs; + struct list stores; +} WINE_COLLECTIONSTORE, *PWINE_COLLECTIONSTORE; + +static void WINAPI CRYPT_CollectionCloseStore(HCERTSTORE store, DWORD dwFlags) +{ + PWINE_COLLECTIONSTORE cs = (PWINE_COLLECTIONSTORE)store; + PWINE_STORE_LIST_ENTRY entry, next; + + TRACE("(%p, %08x)\n", store, dwFlags); + + LIST_FOR_EACH_ENTRY_SAFE(entry, next, &cs->stores, WINE_STORE_LIST_ENTRY, + entry) + { + TRACE("closing %p\n", entry); + CertCloseStore((HCERTSTORE)entry->store, dwFlags); + CryptMemFree(entry); + } + cs->cs.DebugInfo->Spare[0] = 0; + DeleteCriticalSection(&cs->cs); + CRYPT_FreeStore((PWINECRYPT_CERTSTORE)store); +} + +static void *CRYPT_CollectionCreateContextFromChild(PWINE_COLLECTIONSTORE store, + PWINE_STORE_LIST_ENTRY storeEntry, void *child, size_t contextSize, + BOOL addRef) +{ + void *ret = Context_CreateLinkContext(contextSize, child, + sizeof(PWINE_STORE_LIST_ENTRY), addRef); + + if (ret) + *(PWINE_STORE_LIST_ENTRY *)Context_GetExtra(ret, contextSize) + = storeEntry; + + return ret; +} + +static BOOL CRYPT_CollectionAddContext(PWINE_COLLECTIONSTORE store, + unsigned int contextFuncsOffset, void *context, void *toReplace, unsigned int contextSize, + void **pChildContext) +{ + BOOL ret; + void *childContext = NULL; + PWINE_STORE_LIST_ENTRY storeEntry = NULL; + + TRACE("(%p, %d, %p, %p, %d)\n", store, contextFuncsOffset, context, + toReplace, contextSize); + + ret = FALSE; + if (toReplace) + { + void *existingLinked = Context_GetLinkedContext(toReplace, contextSize); + PCONTEXT_FUNCS contextFuncs; + + storeEntry = *(PWINE_STORE_LIST_ENTRY *)Context_GetExtra(toReplace, + contextSize); + contextFuncs = (PCONTEXT_FUNCS)((LPBYTE)storeEntry->store + + contextFuncsOffset); + ret = contextFuncs->addContext(storeEntry->store, context, + existingLinked, childContext); + } + else + { + PWINE_STORE_LIST_ENTRY entry, next; + + EnterCriticalSection(&store->cs); + LIST_FOR_EACH_ENTRY_SAFE(entry, next, &store->stores, + WINE_STORE_LIST_ENTRY, entry) + { + if (entry->dwUpdateFlags & CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG) + { + PCONTEXT_FUNCS contextFuncs = (PCONTEXT_FUNCS)( + (LPBYTE)entry->store + contextFuncsOffset); + + storeEntry = entry; + ret = contextFuncs->addContext(entry->store, context, NULL, + (const void **)&childContext); + break; + } + } + LeaveCriticalSection(&store->cs); + if (!storeEntry) + SetLastError(E_ACCESSDENIED); + } + *pChildContext = childContext; + return ret; +} + +/* Advances a collection enumeration by one context, if possible, where + * advancing means: + * - calling the current store's enumeration function once, and returning + * the enumerated context if one is returned + * - moving to the next store if the current store has no more items, and + * recursively calling itself to get the next item. + * Returns NULL if the collection contains no more items or on error. + * Assumes the collection store's lock is held. + */ +static void *CRYPT_CollectionAdvanceEnum(PWINE_COLLECTIONSTORE store, + PWINE_STORE_LIST_ENTRY storeEntry, PCONTEXT_FUNCS contextFuncs, + PCWINE_CONTEXT_INTERFACE contextInterface, void *pPrev, size_t contextSize) +{ + void *ret, *child; + struct list *storeNext = list_next(&store->stores, &storeEntry->entry); + + TRACE("(%p, %p, %p)\n", store, storeEntry, pPrev); + + if (pPrev) + { + /* Ref-counting funny business: "duplicate" (addref) the child, because + * the free(pPrev) below can cause the ref count to become negative. + */ + child = Context_GetLinkedContext(pPrev, contextSize); + contextInterface->duplicate(child); + child = contextFuncs->enumContext(storeEntry->store, child); + contextInterface->free(pPrev); + pPrev = NULL; + } + else + child = contextFuncs->enumContext(storeEntry->store, NULL); + if (child) + ret = CRYPT_CollectionCreateContextFromChild(store, storeEntry, child, + contextSize, FALSE); + else + { + if (storeNext) + { + /* We always want the same function pointers (from certs, crls) + * in the next store, so use the same offset into the next store. + */ + size_t offset = (LPBYTE)contextFuncs - (LPBYTE)storeEntry->store; + PWINE_STORE_LIST_ENTRY storeNextEntry = + LIST_ENTRY(storeNext, WINE_STORE_LIST_ENTRY, entry); + PCONTEXT_FUNCS storeNextContexts = + (PCONTEXT_FUNCS)((LPBYTE)storeNextEntry->store + offset); + + ret = CRYPT_CollectionAdvanceEnum(store, storeNextEntry, + storeNextContexts, contextInterface, NULL, contextSize); + } + else + { + SetLastError(CRYPT_E_NOT_FOUND); + ret = NULL; + } + } + TRACE("returning %p\n", ret); + return ret; +} + +static BOOL CRYPT_CollectionAddCert(PWINECRYPT_CERTSTORE store, void *cert, + void *toReplace, const void **ppStoreContext) +{ + BOOL ret; + void *childContext = NULL; + PWINE_COLLECTIONSTORE cs = (PWINE_COLLECTIONSTORE)store; + + ret = CRYPT_CollectionAddContext(cs, offsetof(WINECRYPT_CERTSTORE, certs), + cert, toReplace, sizeof(CERT_CONTEXT), &childContext); + if (ppStoreContext && childContext) + { + PWINE_STORE_LIST_ENTRY storeEntry = *(PWINE_STORE_LIST_ENTRY *) + Context_GetExtra(childContext, sizeof(CERT_CONTEXT)); + PCERT_CONTEXT context = + CRYPT_CollectionCreateContextFromChild(cs, storeEntry, childContext, + sizeof(CERT_CONTEXT), TRUE); + + if (context) + context->hCertStore = store; + *ppStoreContext = context; + } + CertFreeCertificateContext((PCCERT_CONTEXT)childContext); + return ret; +} + +static void *CRYPT_CollectionEnumCert(PWINECRYPT_CERTSTORE store, void *pPrev) +{ + PWINE_COLLECTIONSTORE cs = (PWINE_COLLECTIONSTORE)store; + void *ret; + + TRACE("(%p, %p)\n", store, pPrev); + + EnterCriticalSection(&cs->cs); + if (pPrev) + { + PWINE_STORE_LIST_ENTRY storeEntry = + *(PWINE_STORE_LIST_ENTRY *)Context_GetExtra(pPrev, + sizeof(CERT_CONTEXT)); + + ret = CRYPT_CollectionAdvanceEnum(cs, storeEntry, + &storeEntry->store->certs, pCertInterface, pPrev, + sizeof(CERT_CONTEXT)); + } + else + { + if (!list_empty(&cs->stores)) + { + PWINE_STORE_LIST_ENTRY storeEntry = LIST_ENTRY(cs->stores.next, + WINE_STORE_LIST_ENTRY, entry); + + ret = CRYPT_CollectionAdvanceEnum(cs, storeEntry, + &storeEntry->store->certs, pCertInterface, NULL, + sizeof(CERT_CONTEXT)); + } + else + { + SetLastError(CRYPT_E_NOT_FOUND); + ret = NULL; + } + } + LeaveCriticalSection(&cs->cs); + if (ret) + ((PCERT_CONTEXT)ret)->hCertStore = store; + TRACE("returning %p\n", ret); + return ret; +} + +static BOOL CRYPT_CollectionDeleteCert(PWINECRYPT_CERTSTORE store, + void *pCertContext) +{ + BOOL ret; + + TRACE("(%p, %p)\n", store, pCertContext); + + ret = CertDeleteCertificateFromStore((PCCERT_CONTEXT) + Context_GetLinkedContext(pCertContext, sizeof(CERT_CONTEXT))); + return ret; +} + +static BOOL CRYPT_CollectionAddCRL(PWINECRYPT_CERTSTORE store, void *crl, + void *toReplace, const void **ppStoreContext) +{ + BOOL ret; + void *childContext = NULL; + PWINE_COLLECTIONSTORE cs = (PWINE_COLLECTIONSTORE)store; + + ret = CRYPT_CollectionAddContext(cs, offsetof(WINECRYPT_CERTSTORE, crls), + crl, toReplace, sizeof(CRL_CONTEXT), &childContext); + if (ppStoreContext && childContext) + { + PWINE_STORE_LIST_ENTRY storeEntry = *(PWINE_STORE_LIST_ENTRY *) + Context_GetExtra(childContext, sizeof(CRL_CONTEXT)); + PCRL_CONTEXT context = + CRYPT_CollectionCreateContextFromChild(cs, storeEntry, childContext, + sizeof(CRL_CONTEXT), TRUE); + + if (context) + context->hCertStore = store; + *ppStoreContext = context; + } + CertFreeCRLContext((PCCRL_CONTEXT)childContext); + return ret; +} + +static void *CRYPT_CollectionEnumCRL(PWINECRYPT_CERTSTORE store, void *pPrev) +{ + PWINE_COLLECTIONSTORE cs = (PWINE_COLLECTIONSTORE)store; + void *ret; + + TRACE("(%p, %p)\n", store, pPrev); + + EnterCriticalSection(&cs->cs); + if (pPrev) + { + PWINE_STORE_LIST_ENTRY storeEntry = + *(PWINE_STORE_LIST_ENTRY *)Context_GetExtra(pPrev, + sizeof(CRL_CONTEXT)); + + ret = CRYPT_CollectionAdvanceEnum(cs, storeEntry, + &storeEntry->store->crls, pCRLInterface, pPrev, sizeof(CRL_CONTEXT)); + } + else + { + if (!list_empty(&cs->stores)) + { + PWINE_STORE_LIST_ENTRY storeEntry = LIST_ENTRY(cs->stores.next, + WINE_STORE_LIST_ENTRY, entry); + + ret = CRYPT_CollectionAdvanceEnum(cs, storeEntry, + &storeEntry->store->crls, pCRLInterface, NULL, + sizeof(CRL_CONTEXT)); + } + else + { + SetLastError(CRYPT_E_NOT_FOUND); + ret = NULL; + } + } + LeaveCriticalSection(&cs->cs); + if (ret) + ((PCRL_CONTEXT)ret)->hCertStore = store; + TRACE("returning %p\n", ret); + return ret; +} + +static BOOL CRYPT_CollectionDeleteCRL(PWINECRYPT_CERTSTORE store, + void *pCrlContext) +{ + BOOL ret; + + TRACE("(%p, %p)\n", store, pCrlContext); + + ret = CertDeleteCRLFromStore((PCCRL_CONTEXT) + Context_GetLinkedContext(pCrlContext, sizeof(CRL_CONTEXT))); + return ret; +} + +PWINECRYPT_CERTSTORE CRYPT_CollectionOpenStore(HCRYPTPROV hCryptProv, + DWORD dwFlags, const void *pvPara) +{ + PWINE_COLLECTIONSTORE store; + + if (dwFlags & CERT_STORE_DELETE_FLAG) + { + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + store = NULL; + } + else + { + store = CryptMemAlloc(sizeof(WINE_COLLECTIONSTORE)); + if (store) + { + memset(store, 0, sizeof(WINE_COLLECTIONSTORE)); + CRYPT_InitStore(&store->hdr, hCryptProv, dwFlags, + StoreTypeCollection); + store->hdr.closeStore = CRYPT_CollectionCloseStore; + store->hdr.certs.addContext = CRYPT_CollectionAddCert; + store->hdr.certs.enumContext = CRYPT_CollectionEnumCert; + store->hdr.certs.deleteContext = CRYPT_CollectionDeleteCert; + store->hdr.crls.addContext = CRYPT_CollectionAddCRL; + store->hdr.crls.enumContext = CRYPT_CollectionEnumCRL; + store->hdr.crls.deleteContext = CRYPT_CollectionDeleteCRL; + InitializeCriticalSection(&store->cs); + store->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": PWINE_COLLECTIONSTORE->cs"); + list_init(&store->stores); + } + } + return (PWINECRYPT_CERTSTORE)store; +} + +BOOL WINAPI CertAddStoreToCollection(HCERTSTORE hCollectionStore, + HCERTSTORE hSiblingStore, DWORD dwUpdateFlags, DWORD dwPriority) +{ + PWINE_COLLECTIONSTORE collection = (PWINE_COLLECTIONSTORE)hCollectionStore; + WINECRYPT_CERTSTORE *sibling = (WINECRYPT_CERTSTORE *)hSiblingStore; + PWINE_STORE_LIST_ENTRY entry; + BOOL ret; + + TRACE("(%p, %p, %08x, %d)\n", hCollectionStore, hSiblingStore, + dwUpdateFlags, dwPriority); + + if (!collection || !sibling) + return TRUE; + if (collection->hdr.dwMagic != WINE_CRYPTCERTSTORE_MAGIC) + { + SetLastError(E_INVALIDARG); + return FALSE; + } + if (collection->hdr.type != StoreTypeCollection) + { + SetLastError(E_INVALIDARG); + return FALSE; + } + if (sibling->dwMagic != WINE_CRYPTCERTSTORE_MAGIC) + { + SetLastError(E_INVALIDARG); + return FALSE; + } + + entry = CryptMemAlloc(sizeof(WINE_STORE_LIST_ENTRY)); + if (entry) + { + InterlockedIncrement(&sibling->ref); + TRACE("sibling %p's ref count is %d\n", sibling, sibling->ref); + entry->store = sibling; + entry->dwUpdateFlags = dwUpdateFlags; + entry->dwPriority = dwPriority; + list_init(&entry->entry); + TRACE("%p: adding %p, priority %d\n", collection, entry, dwPriority); + EnterCriticalSection(&collection->cs); + if (dwPriority) + { + PWINE_STORE_LIST_ENTRY cursor; + BOOL added = FALSE; + + LIST_FOR_EACH_ENTRY(cursor, &collection->stores, + WINE_STORE_LIST_ENTRY, entry) + { + if (cursor->dwPriority < dwPriority) + { + list_add_before(&cursor->entry, &entry->entry); + added = TRUE; + break; + } + } + if (!added) + list_add_tail(&collection->stores, &entry->entry); + } + else + list_add_tail(&collection->stores, &entry->entry); + LeaveCriticalSection(&collection->cs); + ret = TRUE; + } + else + ret = FALSE; + return ret; +} + +void WINAPI CertRemoveStoreFromCollection(HCERTSTORE hCollectionStore, + HCERTSTORE hSiblingStore) +{ + PWINE_COLLECTIONSTORE collection = (PWINE_COLLECTIONSTORE)hCollectionStore; + WINECRYPT_CERTSTORE *sibling = (WINECRYPT_CERTSTORE *)hSiblingStore; + PWINE_STORE_LIST_ENTRY store, next; + + TRACE("(%p, %p)\n", hCollectionStore, hSiblingStore); + + if (!collection || !sibling) + return; + if (collection->hdr.dwMagic != WINE_CRYPTCERTSTORE_MAGIC) + { + SetLastError(E_INVALIDARG); + return; + } + if (collection->hdr.type != StoreTypeCollection) + return; + if (sibling->dwMagic != WINE_CRYPTCERTSTORE_MAGIC) + { + SetLastError(E_INVALIDARG); + return; + } + EnterCriticalSection(&collection->cs); + LIST_FOR_EACH_ENTRY_SAFE(store, next, &collection->stores, + WINE_STORE_LIST_ENTRY, entry) + { + if (store->store == sibling) + { + list_remove(&store->entry); + CertCloseStore(store->store, 0); + CryptMemFree(store); + break; + } + } + LeaveCriticalSection(&collection->cs); +} diff --git a/dlls/crypt32/crypt32_private.h b/dlls/crypt32/crypt32_private.h index fe1c39ebf69..9f47acfe69f 100644 --- a/dlls/crypt32/crypt32_private.h +++ b/dlls/crypt32/crypt32_private.h @@ -231,6 +231,13 @@ typedef struct WINE_CRYPTCERTSTORE PCONTEXT_PROPERTY_LIST properties; } WINECRYPT_CERTSTORE, *PWINECRYPT_CERTSTORE; +void CRYPT_InitStore(WINECRYPT_CERTSTORE *store, HCRYPTPROV hCryptProv, + DWORD dwFlags, CertStoreType type); +void CRYPT_FreeStore(PWINECRYPT_CERTSTORE store); + +PWINECRYPT_CERTSTORE CRYPT_CollectionOpenStore(HCRYPTPROV hCryptProv, + DWORD dwFlags, const void *pvPara); + /* Helper function for store reading functions and * CertAddSerializedElementToStore. Returns a context of the appropriate type * if it can, or NULL otherwise. Doesn't validate any of the properties in diff --git a/dlls/crypt32/store.c b/dlls/crypt32/store.c index d2687fb99d8..a2b7666e628 100644 --- a/dlls/crypt32/store.c +++ b/dlls/crypt32/store.c @@ -128,21 +128,6 @@ typedef struct _WINE_MSGSTOREINFO HCRYPTMSG msg; } WINE_MSGSTOREINFO, *PWINE_MSGSTOREINFO; -typedef struct _WINE_STORE_LIST_ENTRY -{ - PWINECRYPT_CERTSTORE store; - DWORD dwUpdateFlags; - DWORD dwPriority; - struct list entry; -} WINE_STORE_LIST_ENTRY, *PWINE_STORE_LIST_ENTRY; - -typedef struct _WINE_COLLECTIONSTORE -{ - WINECRYPT_CERTSTORE hdr; - CRITICAL_SECTION cs; - struct list stores; -} WINE_COLLECTIONSTORE, *PWINE_COLLECTIONSTORE; - typedef struct _WINE_PROVIDERSTORE { WINECRYPT_CERTSTORE hdr; @@ -157,7 +142,7 @@ typedef struct _WINE_PROVIDERSTORE PFN_CERT_STORE_PROV_CONTROL provControl; } WINE_PROVIDERSTORE, *PWINE_PROVIDERSTORE; -static void CRYPT_InitStore(WINECRYPT_CERTSTORE *store, HCRYPTPROV hCryptProv, +void CRYPT_InitStore(WINECRYPT_CERTSTORE *store, HCRYPTPROV hCryptProv, DWORD dwFlags, CertStoreType type) { store->ref = 1; @@ -173,7 +158,7 @@ static void CRYPT_InitStore(WINECRYPT_CERTSTORE *store, HCRYPTPROV hCryptProv, store->properties = NULL; } -static void CRYPT_FreeStore(PWINECRYPT_CERTSTORE store) +void CRYPT_FreeStore(PWINECRYPT_CERTSTORE store) { if (store->properties) ContextPropertyList_Free(store->properties); @@ -328,340 +313,6 @@ static WINECRYPT_CERTSTORE *CRYPT_MemOpenStore(HCRYPTPROV hCryptProv, return (PWINECRYPT_CERTSTORE)store; } -static void WINAPI CRYPT_CollectionCloseStore(HCERTSTORE store, DWORD dwFlags) -{ - PWINE_COLLECTIONSTORE cs = (PWINE_COLLECTIONSTORE)store; - PWINE_STORE_LIST_ENTRY entry, next; - - TRACE("(%p, %08x)\n", store, dwFlags); - - LIST_FOR_EACH_ENTRY_SAFE(entry, next, &cs->stores, WINE_STORE_LIST_ENTRY, - entry) - { - TRACE("closing %p\n", entry); - CertCloseStore((HCERTSTORE)entry->store, dwFlags); - CryptMemFree(entry); - } - cs->cs.DebugInfo->Spare[0] = 0; - DeleteCriticalSection(&cs->cs); - CRYPT_FreeStore((PWINECRYPT_CERTSTORE)store); -} - -static void *CRYPT_CollectionCreateContextFromChild(PWINE_COLLECTIONSTORE store, - PWINE_STORE_LIST_ENTRY storeEntry, void *child, size_t contextSize, - BOOL addRef) -{ - void *ret = Context_CreateLinkContext(contextSize, child, - sizeof(PWINE_STORE_LIST_ENTRY), addRef); - - if (ret) - *(PWINE_STORE_LIST_ENTRY *)Context_GetExtra(ret, contextSize) - = storeEntry; - - return ret; -} - -static BOOL CRYPT_CollectionAddContext(PWINE_COLLECTIONSTORE store, - unsigned int contextFuncsOffset, void *context, void *toReplace, unsigned int contextSize, - void **pChildContext) -{ - BOOL ret; - void *childContext = NULL; - PWINE_STORE_LIST_ENTRY storeEntry = NULL; - - TRACE("(%p, %d, %p, %p, %d)\n", store, contextFuncsOffset, context, - toReplace, contextSize); - - ret = FALSE; - if (toReplace) - { - void *existingLinked = Context_GetLinkedContext(toReplace, contextSize); - PCONTEXT_FUNCS contextFuncs; - - storeEntry = *(PWINE_STORE_LIST_ENTRY *)Context_GetExtra(toReplace, - contextSize); - contextFuncs = (PCONTEXT_FUNCS)((LPBYTE)storeEntry->store + - contextFuncsOffset); - ret = contextFuncs->addContext(storeEntry->store, context, - existingLinked, childContext); - } - else - { - PWINE_STORE_LIST_ENTRY entry, next; - - EnterCriticalSection(&store->cs); - LIST_FOR_EACH_ENTRY_SAFE(entry, next, &store->stores, - WINE_STORE_LIST_ENTRY, entry) - { - if (entry->dwUpdateFlags & CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG) - { - PCONTEXT_FUNCS contextFuncs = (PCONTEXT_FUNCS)( - (LPBYTE)entry->store + contextFuncsOffset); - - storeEntry = entry; - ret = contextFuncs->addContext(entry->store, context, NULL, - (const void **)&childContext); - break; - } - } - LeaveCriticalSection(&store->cs); - if (!storeEntry) - SetLastError(E_ACCESSDENIED); - } - *pChildContext = childContext; - return ret; -} - -/* Advances a collection enumeration by one context, if possible, where - * advancing means: - * - calling the current store's enumeration function once, and returning - * the enumerated context if one is returned - * - moving to the next store if the current store has no more items, and - * recursively calling itself to get the next item. - * Returns NULL if the collection contains no more items or on error. - * Assumes the collection store's lock is held. - */ -static void *CRYPT_CollectionAdvanceEnum(PWINE_COLLECTIONSTORE store, - PWINE_STORE_LIST_ENTRY storeEntry, PCONTEXT_FUNCS contextFuncs, - PCWINE_CONTEXT_INTERFACE contextInterface, void *pPrev, size_t contextSize) -{ - void *ret, *child; - struct list *storeNext = list_next(&store->stores, &storeEntry->entry); - - TRACE("(%p, %p, %p)\n", store, storeEntry, pPrev); - - if (pPrev) - { - /* Ref-counting funny business: "duplicate" (addref) the child, because - * the free(pPrev) below can cause the ref count to become negative. - */ - child = Context_GetLinkedContext(pPrev, contextSize); - contextInterface->duplicate(child); - child = contextFuncs->enumContext(storeEntry->store, child); - contextInterface->free(pPrev); - pPrev = NULL; - } - else - child = contextFuncs->enumContext(storeEntry->store, NULL); - if (child) - ret = CRYPT_CollectionCreateContextFromChild(store, storeEntry, child, - contextSize, FALSE); - else - { - if (storeNext) - { - /* We always want the same function pointers (from certs, crls) - * in the next store, so use the same offset into the next store. - */ - size_t offset = (LPBYTE)contextFuncs - (LPBYTE)storeEntry->store; - PWINE_STORE_LIST_ENTRY storeNextEntry = - LIST_ENTRY(storeNext, WINE_STORE_LIST_ENTRY, entry); - PCONTEXT_FUNCS storeNextContexts = - (PCONTEXT_FUNCS)((LPBYTE)storeNextEntry->store + offset); - - ret = CRYPT_CollectionAdvanceEnum(store, storeNextEntry, - storeNextContexts, contextInterface, NULL, contextSize); - } - else - { - SetLastError(CRYPT_E_NOT_FOUND); - ret = NULL; - } - } - TRACE("returning %p\n", ret); - return ret; -} - -static BOOL CRYPT_CollectionAddCert(PWINECRYPT_CERTSTORE store, void *cert, - void *toReplace, const void **ppStoreContext) -{ - BOOL ret; - void *childContext = NULL; - PWINE_COLLECTIONSTORE cs = (PWINE_COLLECTIONSTORE)store; - - ret = CRYPT_CollectionAddContext(cs, offsetof(WINECRYPT_CERTSTORE, certs), - cert, toReplace, sizeof(CERT_CONTEXT), &childContext); - if (ppStoreContext && childContext) - { - PWINE_STORE_LIST_ENTRY storeEntry = *(PWINE_STORE_LIST_ENTRY *) - Context_GetExtra(childContext, sizeof(CERT_CONTEXT)); - PCERT_CONTEXT context = - CRYPT_CollectionCreateContextFromChild(cs, storeEntry, childContext, - sizeof(CERT_CONTEXT), TRUE); - - if (context) - context->hCertStore = store; - *ppStoreContext = context; - } - CertFreeCertificateContext((PCCERT_CONTEXT)childContext); - return ret; -} - -static void *CRYPT_CollectionEnumCert(PWINECRYPT_CERTSTORE store, void *pPrev) -{ - PWINE_COLLECTIONSTORE cs = (PWINE_COLLECTIONSTORE)store; - void *ret; - - TRACE("(%p, %p)\n", store, pPrev); - - EnterCriticalSection(&cs->cs); - if (pPrev) - { - PWINE_STORE_LIST_ENTRY storeEntry = - *(PWINE_STORE_LIST_ENTRY *)Context_GetExtra(pPrev, - sizeof(CERT_CONTEXT)); - - ret = CRYPT_CollectionAdvanceEnum(cs, storeEntry, - &storeEntry->store->certs, pCertInterface, pPrev, - sizeof(CERT_CONTEXT)); - } - else - { - if (!list_empty(&cs->stores)) - { - PWINE_STORE_LIST_ENTRY storeEntry = LIST_ENTRY(cs->stores.next, - WINE_STORE_LIST_ENTRY, entry); - - ret = CRYPT_CollectionAdvanceEnum(cs, storeEntry, - &storeEntry->store->certs, pCertInterface, NULL, - sizeof(CERT_CONTEXT)); - } - else - { - SetLastError(CRYPT_E_NOT_FOUND); - ret = NULL; - } - } - LeaveCriticalSection(&cs->cs); - if (ret) - ((PCERT_CONTEXT)ret)->hCertStore = store; - TRACE("returning %p\n", ret); - return ret; -} - -static BOOL CRYPT_CollectionDeleteCert(PWINECRYPT_CERTSTORE store, - void *pCertContext) -{ - BOOL ret; - - TRACE("(%p, %p)\n", store, pCertContext); - - ret = CertDeleteCertificateFromStore((PCCERT_CONTEXT) - Context_GetLinkedContext(pCertContext, sizeof(CERT_CONTEXT))); - return ret; -} - -static BOOL CRYPT_CollectionAddCRL(PWINECRYPT_CERTSTORE store, void *crl, - void *toReplace, const void **ppStoreContext) -{ - BOOL ret; - void *childContext = NULL; - PWINE_COLLECTIONSTORE cs = (PWINE_COLLECTIONSTORE)store; - - ret = CRYPT_CollectionAddContext(cs, offsetof(WINECRYPT_CERTSTORE, crls), - crl, toReplace, sizeof(CRL_CONTEXT), &childContext); - if (ppStoreContext && childContext) - { - PWINE_STORE_LIST_ENTRY storeEntry = *(PWINE_STORE_LIST_ENTRY *) - Context_GetExtra(childContext, sizeof(CRL_CONTEXT)); - PCRL_CONTEXT context = - CRYPT_CollectionCreateContextFromChild(cs, storeEntry, childContext, - sizeof(CRL_CONTEXT), TRUE); - - if (context) - context->hCertStore = store; - *ppStoreContext = context; - } - CertFreeCRLContext((PCCRL_CONTEXT)childContext); - return ret; -} - -static void *CRYPT_CollectionEnumCRL(PWINECRYPT_CERTSTORE store, void *pPrev) -{ - PWINE_COLLECTIONSTORE cs = (PWINE_COLLECTIONSTORE)store; - void *ret; - - TRACE("(%p, %p)\n", store, pPrev); - - EnterCriticalSection(&cs->cs); - if (pPrev) - { - PWINE_STORE_LIST_ENTRY storeEntry = - *(PWINE_STORE_LIST_ENTRY *)Context_GetExtra(pPrev, - sizeof(CRL_CONTEXT)); - - ret = CRYPT_CollectionAdvanceEnum(cs, storeEntry, - &storeEntry->store->crls, pCRLInterface, pPrev, sizeof(CRL_CONTEXT)); - } - else - { - if (!list_empty(&cs->stores)) - { - PWINE_STORE_LIST_ENTRY storeEntry = LIST_ENTRY(cs->stores.next, - WINE_STORE_LIST_ENTRY, entry); - - ret = CRYPT_CollectionAdvanceEnum(cs, storeEntry, - &storeEntry->store->crls, pCRLInterface, NULL, - sizeof(CRL_CONTEXT)); - } - else - { - SetLastError(CRYPT_E_NOT_FOUND); - ret = NULL; - } - } - LeaveCriticalSection(&cs->cs); - if (ret) - ((PCRL_CONTEXT)ret)->hCertStore = store; - TRACE("returning %p\n", ret); - return ret; -} - -static BOOL CRYPT_CollectionDeleteCRL(PWINECRYPT_CERTSTORE store, - void *pCrlContext) -{ - BOOL ret; - - TRACE("(%p, %p)\n", store, pCrlContext); - - ret = CertDeleteCRLFromStore((PCCRL_CONTEXT) - Context_GetLinkedContext(pCrlContext, sizeof(CRL_CONTEXT))); - return ret; -} - -static WINECRYPT_CERTSTORE *CRYPT_CollectionOpenStore(HCRYPTPROV hCryptProv, - DWORD dwFlags, const void *pvPara) -{ - PWINE_COLLECTIONSTORE store; - - if (dwFlags & CERT_STORE_DELETE_FLAG) - { - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - store = NULL; - } - else - { - store = CryptMemAlloc(sizeof(WINE_COLLECTIONSTORE)); - if (store) - { - memset(store, 0, sizeof(WINE_COLLECTIONSTORE)); - CRYPT_InitStore(&store->hdr, hCryptProv, dwFlags, - StoreTypeCollection); - store->hdr.closeStore = CRYPT_CollectionCloseStore; - store->hdr.certs.addContext = CRYPT_CollectionAddCert; - store->hdr.certs.enumContext = CRYPT_CollectionEnumCert; - store->hdr.certs.deleteContext = CRYPT_CollectionDeleteCert; - store->hdr.crls.addContext = CRYPT_CollectionAddCRL; - store->hdr.crls.enumContext = CRYPT_CollectionEnumCRL; - store->hdr.crls.deleteContext = CRYPT_CollectionDeleteCRL; - InitializeCriticalSection(&store->cs); - store->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": PWINE_COLLECTIONSTORE->cs"); - list_init(&store->stores); - } - } - return (PWINECRYPT_CERTSTORE)store; -} - static void WINAPI CRYPT_ProvCloseStore(HCERTSTORE hCertStore, DWORD dwFlags) { PWINE_PROVIDERSTORE store = (PWINE_PROVIDERSTORE)hCertStore; @@ -2665,112 +2316,6 @@ BOOL WINAPI CertSetCTLContextProperty(PCCTL_CONTEXT pCTLContext, return FALSE; } -BOOL WINAPI CertAddStoreToCollection(HCERTSTORE hCollectionStore, - HCERTSTORE hSiblingStore, DWORD dwUpdateFlags, DWORD dwPriority) -{ - PWINE_COLLECTIONSTORE collection = (PWINE_COLLECTIONSTORE)hCollectionStore; - WINECRYPT_CERTSTORE *sibling = (WINECRYPT_CERTSTORE *)hSiblingStore; - PWINE_STORE_LIST_ENTRY entry; - BOOL ret; - - TRACE("(%p, %p, %08x, %d)\n", hCollectionStore, hSiblingStore, - dwUpdateFlags, dwPriority); - - if (!collection || !sibling) - return TRUE; - if (collection->hdr.dwMagic != WINE_CRYPTCERTSTORE_MAGIC) - { - SetLastError(E_INVALIDARG); - return FALSE; - } - if (collection->hdr.type != StoreTypeCollection) - { - SetLastError(E_INVALIDARG); - return FALSE; - } - if (sibling->dwMagic != WINE_CRYPTCERTSTORE_MAGIC) - { - SetLastError(E_INVALIDARG); - return FALSE; - } - - entry = CryptMemAlloc(sizeof(WINE_STORE_LIST_ENTRY)); - if (entry) - { - InterlockedIncrement(&sibling->ref); - TRACE("sibling %p's ref count is %d\n", sibling, sibling->ref); - entry->store = sibling; - entry->dwUpdateFlags = dwUpdateFlags; - entry->dwPriority = dwPriority; - list_init(&entry->entry); - TRACE("%p: adding %p, priority %d\n", collection, entry, dwPriority); - EnterCriticalSection(&collection->cs); - if (dwPriority) - { - PWINE_STORE_LIST_ENTRY cursor; - BOOL added = FALSE; - - LIST_FOR_EACH_ENTRY(cursor, &collection->stores, - WINE_STORE_LIST_ENTRY, entry) - { - if (cursor->dwPriority < dwPriority) - { - list_add_before(&cursor->entry, &entry->entry); - added = TRUE; - break; - } - } - if (!added) - list_add_tail(&collection->stores, &entry->entry); - } - else - list_add_tail(&collection->stores, &entry->entry); - LeaveCriticalSection(&collection->cs); - ret = TRUE; - } - else - ret = FALSE; - return ret; -} - -void WINAPI CertRemoveStoreFromCollection(HCERTSTORE hCollectionStore, - HCERTSTORE hSiblingStore) -{ - PWINE_COLLECTIONSTORE collection = (PWINE_COLLECTIONSTORE)hCollectionStore; - WINECRYPT_CERTSTORE *sibling = (WINECRYPT_CERTSTORE *)hSiblingStore; - PWINE_STORE_LIST_ENTRY store, next; - - TRACE("(%p, %p)\n", hCollectionStore, hSiblingStore); - - if (!collection || !sibling) - return; - if (collection->hdr.dwMagic != WINE_CRYPTCERTSTORE_MAGIC) - { - SetLastError(E_INVALIDARG); - return; - } - if (collection->hdr.type != StoreTypeCollection) - return; - if (sibling->dwMagic != WINE_CRYPTCERTSTORE_MAGIC) - { - SetLastError(E_INVALIDARG); - return; - } - EnterCriticalSection(&collection->cs); - LIST_FOR_EACH_ENTRY_SAFE(store, next, &collection->stores, - WINE_STORE_LIST_ENTRY, entry) - { - if (store->store == sibling) - { - list_remove(&store->entry); - CertCloseStore(store->store, 0); - CryptMemFree(store); - break; - } - } - LeaveCriticalSection(&collection->cs); -} - static LONG CRYPT_OpenParentStore(DWORD dwFlags, void *pvSystemStoreLocationPara, HKEY *key) {