From 9fb1e4d675043bd078552a7c0de8eec317473cd0 Mon Sep 17 00:00:00 2001 From: Jacek Caban Date: Fri, 18 Oct 2013 10:50:43 +0200 Subject: [PATCH] crypt32: Keep reference to store in contexts. --- dlls/crypt32/cert.c | 12 ++--- dlls/crypt32/collectionstore.c | 22 ++++----- dlls/crypt32/context.c | 68 +++++++++++++++++--------- dlls/crypt32/crl.c | 4 +- dlls/crypt32/crypt32_private.h | 11 ++--- dlls/crypt32/ctl.c | 4 +- dlls/crypt32/provstore.c | 11 +++++ dlls/crypt32/store.c | 30 ++++++++---- dlls/crypt32/tests/store.c | 88 ++++++++++++++++++++++++++++++++++ 9 files changed, 190 insertions(+), 60 deletions(-) diff --git a/dlls/crypt32/cert.c b/dlls/crypt32/cert.c index 2a685448ed7..f2889f9fec0 100644 --- a/dlls/crypt32/cert.c +++ b/dlls/crypt32/cert.c @@ -124,7 +124,7 @@ static context_t *Cert_clone(context_t *context, WINECRYPT_CERTSTORE *store, BOO cert_t *cert; if(use_link) { - cert = (cert_t*)Context_CreateLinkContext(sizeof(CERT_CONTEXT), context); + cert = (cert_t*)Context_CreateLinkContext(sizeof(CERT_CONTEXT), context, store); if(!cert) return NULL; }else { @@ -133,7 +133,7 @@ static context_t *Cert_clone(context_t *context, WINECRYPT_CERTSTORE *store, BOO DWORD size = 0; BOOL res; - new_context = Context_CreateDataContext(sizeof(CERT_CONTEXT), &cert_vtbl); + new_context = Context_CreateDataContext(sizeof(CERT_CONTEXT), &cert_vtbl, store); if(!new_context) return NULL; cert = cert_from_ptr(new_context); @@ -270,12 +270,10 @@ BOOL WINAPI add_cert_to_store(WINECRYPT_CERTSTORE *store, const CERT_CONTEXT *ce if(inherit_props) Context_CopyProperties(context_ptr(new_context), existing); - if(ret_context) { - Context_AddRef(new_context); + if(ret_context) *ret_context = context_ptr(new_context); - }else if(new_context) { + else if(new_context) Context_Release(new_context); - } TRACE("returning %d\n", ret); return ret; @@ -335,7 +333,7 @@ PCCERT_CONTEXT WINAPI CertCreateCertificateContext(DWORD dwCertEncodingType, { BYTE *data = NULL; - cert = Context_CreateDataContext(sizeof(CERT_CONTEXT), &cert_vtbl); + cert = Context_CreateDataContext(sizeof(CERT_CONTEXT), &cert_vtbl, &empty_store); if (!cert) goto end; data = CryptMemAlloc(cbCertEncoded); diff --git a/dlls/crypt32/collectionstore.c b/dlls/crypt32/collectionstore.c index b5d1b8b388e..6abcef09632 100644 --- a/dlls/crypt32/collectionstore.c +++ b/dlls/crypt32/collectionstore.c @@ -71,6 +71,12 @@ static DWORD Collection_release(WINECRYPT_CERTSTORE *store, DWORD flags) return ERROR_SUCCESS; } +static void Collection_releaseContext(WINECRYPT_CERTSTORE *store, context_t *context) +{ + /* We don't cache context links, so just free them. */ + Context_Free(context); +} + static context_t *CRYPT_CollectionCreateContextFromChild(WINE_COLLECTIONSTORE *store, WINE_STORE_LIST_ENTRY *storeEntry, context_t *child) { @@ -256,14 +262,11 @@ static BOOL Collection_deleteCert(WINECRYPT_CERTSTORE *store, context_t *context { cert_t *cert = (cert_t*)context; cert_t *linked; - BOOL ret; TRACE("(%p, %p)\n", store, cert); linked = (cert_t*)context->linked; - ret = CertDeleteCertificateFromStore(&linked->ctx); - Context_Release(&cert->base); - return ret; + return CertDeleteCertificateFromStore(&linked->ctx); } static BOOL Collection_addCRL(WINECRYPT_CERTSTORE *store, context_t *crl, @@ -327,14 +330,11 @@ static context_t *Collection_enumCRL(WINECRYPT_CERTSTORE *store, context_t *prev static BOOL Collection_deleteCRL(WINECRYPT_CERTSTORE *store, context_t *context) { crl_t *crl = (crl_t*)context, *linked; - BOOL ret; TRACE("(%p, %p)\n", store, crl); linked = (crl_t*)context->linked; - ret = CertDeleteCRLFromStore(&linked->ctx); - Context_Release(&crl->base); - return ret; + return CertDeleteCRLFromStore(&linked->ctx); } static BOOL Collection_addCTL(WINECRYPT_CERTSTORE *store, context_t *ctl, @@ -398,14 +398,11 @@ static context_t *Collection_enumCTL(WINECRYPT_CERTSTORE *store, context_t *prev static BOOL Collection_deleteCTL(WINECRYPT_CERTSTORE *store, context_t *context) { ctl_t *ctl = (ctl_t*)context, *linked; - BOOL ret; TRACE("(%p, %p)\n", store, ctl); linked = (ctl_t*)context->linked; - ret = CertDeleteCTLFromStore(&linked->ctx); - Context_Release(&ctl->base); - return ret; + return CertDeleteCTLFromStore(&linked->ctx); } static BOOL Collection_control(WINECRYPT_CERTSTORE *cert_store, DWORD dwFlags, @@ -448,6 +445,7 @@ static BOOL Collection_control(WINECRYPT_CERTSTORE *cert_store, DWORD dwFlags, static const store_vtbl_t CollectionStoreVtbl = { Collection_addref, Collection_release, + Collection_releaseContext, Collection_control, { Collection_addCert, diff --git a/dlls/crypt32/context.c b/dlls/crypt32/context.c index d836b6fe36f..6dc46c2c012 100644 --- a/dlls/crypt32/context.c +++ b/dlls/crypt32/context.c @@ -25,7 +25,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(context); -void *Context_CreateDataContext(size_t contextSize, const context_vtbl_t *vtbl) +void *Context_CreateDataContext(size_t contextSize, const context_vtbl_t *vtbl, WINECRYPT_CERTSTORE *store) { context_t *context; @@ -33,9 +33,6 @@ void *Context_CreateDataContext(size_t contextSize, const context_vtbl_t *vtbl) if (!context) return NULL; - context->vtbl = vtbl; - context->ref = 1; - context->linked = NULL; context->properties = ContextPropertyList_Create(); if (!context->properties) { @@ -43,11 +40,18 @@ void *Context_CreateDataContext(size_t contextSize, const context_vtbl_t *vtbl) return NULL; } + context->vtbl = vtbl; + context->ref = 1; + context->linked = NULL; + + store->vtbl->addref(store); + context->store = store; + TRACE("returning %p\n", context); return context_ptr(context); } -context_t *Context_CreateLinkContext(unsigned int contextSize, context_t *linked) +context_t *Context_CreateLinkContext(unsigned int contextSize, context_t *linked, WINECRYPT_CERTSTORE *store) { context_t *context; @@ -64,36 +68,54 @@ context_t *Context_CreateLinkContext(unsigned int contextSize, context_t *linked context->properties = linked->properties; Context_AddRef(linked); + store->vtbl->addref(store); + context->store = store; + TRACE("returning %p\n", context); return context; } void Context_AddRef(context_t *context) { - InterlockedIncrement(&context->ref); + LONG ref = InterlockedIncrement(&context->ref); + TRACE("(%p) ref=%d\n", context, context->ref); + + if(ref == 1) { + /* This is the first external (non-store) reference. Increase store ref cnt. */ + context->store->vtbl->addref(context->store); + } +} + +void Context_Free(context_t *context) +{ + TRACE("(%p)\n", context); + + assert(!context->ref); + + if (!context->linked) { + ContextPropertyList_Free(context->properties); + context->vtbl->free(context); + }else { + Context_Release(context->linked); + } + + CryptMemFree(context); } void Context_Release(context_t *context) { - if (context->ref <= 0) - { - ERR("%p's ref count is %d\n", context, context->ref); + LONG ref = InterlockedDecrement(&context->ref); + + TRACE("(%p) ref=%d\n", context, ref); + assert(ref >= 0); + + if (!ref) { + /* This is the last reference, but the context still may be in a store. + * We release our store reference, but leave it up to store to free or keep the context. */ + context->store->vtbl->releaseContext(context->store, context); + context->store->vtbl->release(context->store, 0); } - if (InterlockedDecrement(&context->ref) == 0) - { - TRACE("freeing %p\n", context); - if (!context->linked) - { - ContextPropertyList_Free(context->properties); - context->vtbl->free(context); - } else { - Context_Release(context->linked); - } - CryptMemFree(context); - } - else - TRACE("%p's ref count is %d\n", context, context->ref); } void Context_CopyProperties(const void *to, const void *from) diff --git a/dlls/crypt32/crl.c b/dlls/crypt32/crl.c index 967231b15b0..bf67a6b3adc 100644 --- a/dlls/crypt32/crl.c +++ b/dlls/crypt32/crl.c @@ -46,7 +46,7 @@ static context_t *CRL_clone(context_t *context, WINECRYPT_CERTSTORE *store, BOOL return NULL; } - crl = (crl_t*)Context_CreateLinkContext(sizeof(CRL_CONTEXT), context); + crl = (crl_t*)Context_CreateLinkContext(sizeof(CRL_CONTEXT), context, store); if(!crl) return NULL; @@ -82,7 +82,7 @@ PCCRL_CONTEXT WINAPI CertCreateCRLContext(DWORD dwCertEncodingType, { BYTE *data = NULL; - crl = Context_CreateDataContext(sizeof(CRL_CONTEXT), &crl_vtbl); + crl = Context_CreateDataContext(sizeof(CRL_CONTEXT), &crl_vtbl, &empty_store); if (!crl) goto end; data = CryptMemAlloc(cbCrlEncoded); diff --git a/dlls/crypt32/crypt32_private.h b/dlls/crypt32/crypt32_private.h index 50eb9e6b37b..2dbc1ce3858 100644 --- a/dlls/crypt32/crypt32_private.h +++ b/dlls/crypt32/crypt32_private.h @@ -174,6 +174,7 @@ typedef struct { struct _context_t { const context_vtbl_t *vtbl; LONG ref; + struct WINE_CRYPTCERTSTORE *store; struct _context_t *linked; CONTEXT_PROPERTY_LIST *properties; union { @@ -297,6 +298,7 @@ typedef enum _CertStoreType { typedef struct { void (*addref)(struct WINE_CRYPTCERTSTORE*); DWORD (*release)(struct WINE_CRYPTCERTSTORE*,DWORD); + void (*releaseContext)(struct WINE_CRYPTCERTSTORE*,context_t*); BOOL (*control)(struct WINE_CRYPTCERTSTORE*,DWORD,DWORD,void const*); CONTEXT_FUNCS certs; CONTEXT_FUNCS crls; @@ -387,24 +389,21 @@ DWORD cert_name_to_str_with_indent(DWORD dwCertEncodingType, DWORD indent, * which should be one of CERT_CONTEXT, CRL_CONTEXT, or CTL_CONTEXT. * Free with Context_Release. */ -void *Context_CreateDataContext(size_t contextSize, const context_vtbl_t *vtbl) DECLSPEC_HIDDEN; +void *Context_CreateDataContext(size_t contextSize, const context_vtbl_t *vtbl, struct WINE_CRYPTCERTSTORE*) DECLSPEC_HIDDEN; /* Creates a new link context. The context refers to linked * rather than owning its own properties. If addRef is TRUE (which ordinarily * it should be) linked is addref'd. * Free with Context_Release. */ -context_t *Context_CreateLinkContext(unsigned contextSize, context_t *linked) DECLSPEC_HIDDEN; +context_t *Context_CreateLinkContext(unsigned contextSize, context_t *linked, struct WINE_CRYPTCERTSTORE*) DECLSPEC_HIDDEN; /* Copies properties from fromContext to toContext. */ void Context_CopyProperties(const void *to, const void *from) DECLSPEC_HIDDEN; void Context_AddRef(context_t*) DECLSPEC_HIDDEN; - -/* Decrements context's ref count. If context is a link context, releases its - * linked context as well. - */ void Context_Release(context_t *context) DECLSPEC_HIDDEN; +void Context_Free(context_t*) DECLSPEC_HIDDEN; /** * Context property list functions diff --git a/dlls/crypt32/ctl.c b/dlls/crypt32/ctl.c index 1f95fdf9a2a..ef5410a0367 100644 --- a/dlls/crypt32/ctl.c +++ b/dlls/crypt32/ctl.c @@ -48,7 +48,7 @@ static context_t *CTL_clone(context_t *context, WINECRYPT_CERTSTORE *store, BOOL return NULL; } - ctl = (ctl_t*)Context_CreateLinkContext(sizeof(CTL_CONTEXT), context); + ctl = (ctl_t*)Context_CreateLinkContext(sizeof(CTL_CONTEXT), context, store); if(!ctl) return NULL; @@ -440,7 +440,7 @@ PCCTL_CONTEXT WINAPI CertCreateCTLContext(DWORD dwMsgAndCertEncodingType, &ctlInfo, &size); if (ret) { - ctl = Context_CreateDataContext(sizeof(CTL_CONTEXT), &ctl_vtbl); + ctl = Context_CreateDataContext(sizeof(CTL_CONTEXT), &ctl_vtbl, &empty_store); if (ctl) { BYTE *data = CryptMemAlloc(cbCtlEncoded); diff --git a/dlls/crypt32/provstore.c b/dlls/crypt32/provstore.c index b406cca49e4..a6f7130be8e 100644 --- a/dlls/crypt32/provstore.c +++ b/dlls/crypt32/provstore.c @@ -15,7 +15,10 @@ * 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 + #include "windef.h" #include "winbase.h" #include "wincrypt.h" @@ -68,6 +71,13 @@ static DWORD ProvStore_release(WINECRYPT_CERTSTORE *cert_store, DWORD flags) return ERROR_SUCCESS; } +static void ProvStore_releaseContext(WINECRYPT_CERTSTORE *store, context_t *context) +{ + /* As long as we don't have contexts properly stored (and hack around hCertStore + in add* and enum* functions), this function should never be called. */ + assert(0); +} + static BOOL ProvStore_addCert(WINECRYPT_CERTSTORE *store, context_t *cert, context_t *toReplace, context_t **ppStoreContext, BOOL use_link) { @@ -277,6 +287,7 @@ static BOOL ProvStore_control(WINECRYPT_CERTSTORE *cert_store, DWORD dwFlags, DW static const store_vtbl_t ProvStoreVtbl = { ProvStore_addref, ProvStore_release, + ProvStore_releaseContext, ProvStore_control, { ProvStore_addCert, diff --git a/dlls/crypt32/store.c b/dlls/crypt32/store.c index 07613ec5404..70c9150b5f0 100644 --- a/dlls/crypt32/store.c +++ b/dlls/crypt32/store.c @@ -160,17 +160,17 @@ static BOOL MemStore_addContext(WINE_MEMSTORE *store, struct list *list, context context->u.entry.prev->next = &context->u.entry; context->u.entry.next->prev = &context->u.entry; list_init(&existing->u.entry); - Context_Release(existing); + if(!existing->ref) + Context_Release(existing); }else { list_add_head(list, &context->u.entry); } LeaveCriticalSection(&store->cs); - if(ret_context) { - Context_AddRef(context); + if(ret_context) *ret_context = context; - } - + else + Context_Release(context); return TRUE; } @@ -210,8 +210,8 @@ static BOOL MemStore_deleteContext(WINE_MEMSTORE *store, context_t *context) } LeaveCriticalSection(&store->cs); - if(in_list) - Context_Release(context); + if(in_list && !context->ref) + Context_Free(context); return TRUE; } @@ -223,10 +223,17 @@ static void free_contexts(struct list *list) { TRACE("freeing %p\n", context); list_remove(&context->u.entry); - Context_Release(context); + Context_Free(context); } } +static void MemStore_releaseContext(WINECRYPT_CERTSTORE *store, context_t *context) +{ + /* Free the context only if it's not in a list. Otherwise it may be reused later. */ + if(list_empty(&context->u.entry)) + Context_Free(context); +} + static BOOL MemStore_addCert(WINECRYPT_CERTSTORE *store, context_t *cert, context_t *toReplace, context_t **ppStoreContext, BOOL use_link) { @@ -348,6 +355,7 @@ static BOOL MemStore_control(WINECRYPT_CERTSTORE *store, DWORD dwFlags, static const store_vtbl_t MemStoreVtbl = { MemStore_addref, MemStore_release, + MemStore_releaseContext, MemStore_control, { MemStore_addCert, @@ -1401,6 +1409,11 @@ static DWORD EmptyStore_release(WINECRYPT_CERTSTORE *store, DWORD flags) return E_UNEXPECTED; } +static void EmptyStore_releaseContext(WINECRYPT_CERTSTORE *store, context_t *context) +{ + Context_Free(context); +} + static BOOL EmptyStore_add(WINECRYPT_CERTSTORE *store, context_t *context, context_t *replace, context_t **ret_context, BOOL use_link) { @@ -1439,6 +1452,7 @@ static BOOL EmptyStore_control(WINECRYPT_CERTSTORE *store, DWORD flags, DWORD ct static const store_vtbl_t EmptyStoreVtbl = { EmptyStore_addref, EmptyStore_release, + EmptyStore_releaseContext, EmptyStore_control, { EmptyStore_add, diff --git a/dlls/crypt32/tests/store.c b/dlls/crypt32/tests/store.c index 2e852fb1e46..5e995037f74 100644 --- a/dlls/crypt32/tests/store.c +++ b/dlls/crypt32/tests/store.c @@ -93,6 +93,26 @@ static const BYTE bigCert2[] = { 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 }; +static const BYTE signedCTLWithCTLInnerContent[] = { +0x30,0x82,0x01,0x0f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02, +0xa0,0x82,0x01,0x00,0x30,0x81,0xfd,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06, +0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x30,0x06,0x09, +0x2b,0x06,0x01,0x04,0x01,0x82,0x37,0x0a,0x01,0xa0,0x23,0x30,0x21,0x30,0x00, +0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30, +0x30,0x5a,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05, +0x00,0x31,0x81,0xb5,0x30,0x81,0xb2,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,0x31, +0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20, +0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48, +0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0xa0,0x3b,0x30,0x18,0x06,0x09,0x2a,0x86, +0x48,0x86,0xf7,0x0d,0x01,0x09,0x03,0x31,0x0b,0x06,0x09,0x2b,0x06,0x01,0x04, +0x01,0x82,0x37,0x0a,0x01,0x30,0x1f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d, +0x01,0x09,0x04,0x31,0x12,0x04,0x10,0x54,0x71,0xbc,0xe1,0x56,0x31,0xa2,0xf9, +0x65,0x70,0x34,0xf8,0xe2,0xe9,0xb4,0xf4,0x30,0x04,0x06,0x00,0x05,0x00,0x04, +0x40,0x2f,0x1b,0x9f,0x5a,0x4a,0x15,0x73,0xfa,0xb1,0x93,0x3d,0x09,0x52,0xdf, +0x6b,0x98,0x4b,0x13,0x5e,0xe7,0xbf,0x65,0xf4,0x9c,0xc2,0xb1,0x77,0x09,0xb1, +0x66,0x4d,0x72,0x0d,0xb1,0x1a,0x50,0x20,0xe0,0x57,0xa2,0x39,0xc7,0xcd,0x7f, +0x8e,0xe7,0x5f,0x76,0x2b,0xd1,0x6a,0x82,0xb3,0x30,0x25,0x61,0xf6,0x25,0x23, +0x57,0x6c,0x0b,0x47,0xb8 }; static BOOL (WINAPI *pCertAddStoreToCollection)(HCERTSTORE,HCERTSTORE,DWORD,DWORD); @@ -2571,6 +2591,9 @@ static void testEmptyStore(void) static void testCloseStore(void) { + const CERT_CONTEXT *cert; + const CRL_CONTEXT *crl; + const CTL_CONTEXT *ctl; HCERTSTORE store, store2; BOOL res; @@ -2592,6 +2615,71 @@ static void testCloseStore(void) res = CertCloseStore(store2, CERT_CLOSE_STORE_CHECK_FLAG); ok(res, "CertCloseStore failed\n"); + + store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0, CERT_STORE_CREATE_NEW_FLAG, NULL); + ok(store != NULL, "CertOpenStore failed\n"); + + res = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING, bigCert, + sizeof(bigCert), CERT_STORE_ADD_ALWAYS, &cert); + ok(res, "CertAddEncodedCertificateToStore failed\n"); + + /* There is still a reference from cert */ + res = CertCloseStore(store, CERT_CLOSE_STORE_CHECK_FLAG); + ok(!res && GetLastError() == CRYPT_E_PENDING_CLOSE, "CertCloseStore failed\n"); + + res = CertFreeCertificateContext(cert); + ok(res, "CertFreeCertificateContext failed\n"); + + store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0, CERT_STORE_CREATE_NEW_FLAG, NULL); + ok(store != NULL, "CertOpenStore failed\n"); + + res = CertAddEncodedCRLToStore(store, X509_ASN_ENCODING, signedCRL, + sizeof(signedCRL), CERT_STORE_ADD_ALWAYS, &crl); + ok(res, "CertAddEncodedCRLToStore failed\n"); + + /* There is still a reference from CRL */ + res = CertCloseStore(store, CERT_CLOSE_STORE_CHECK_FLAG); + ok(!res && GetLastError() == CRYPT_E_PENDING_CLOSE, "CertCloseStore failed\n"); + + res = CertFreeCRLContext(crl); + ok(res, "CertFreeCRLContext failed\n"); + + store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0, CERT_STORE_CREATE_NEW_FLAG, NULL); + ok(store != NULL, "CertOpenStore failed\n"); + + res = CertAddEncodedCTLToStore(store, X509_ASN_ENCODING, signedCTLWithCTLInnerContent, + sizeof(signedCTLWithCTLInnerContent), CERT_STORE_ADD_ALWAYS, &ctl); + ok(res, "CertAddEncodedCTLToStore failed\n"); + + /* There is still a reference from CTL */ + res = CertCloseStore(store, CERT_CLOSE_STORE_CHECK_FLAG); + ok(!res && GetLastError() == CRYPT_E_PENDING_CLOSE, "CertCloseStore returned: %x(%u)\n", res, GetLastError()); + + res = CertFreeCTLContext(ctl); + ok(res, "CertFreeCTLContext failed\n"); + + /* Add all kinds of contexts, then release external references and make sure that store is properly closed. */ + store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0, CERT_STORE_CREATE_NEW_FLAG, NULL); + ok(store != NULL, "CertOpenStore failed\n"); + + res = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING, bigCert, + sizeof(bigCert), CERT_STORE_ADD_ALWAYS, &cert); + ok(res, "CertAddEncodedCertificateToStore failed\n"); + + res = CertAddEncodedCRLToStore(store, X509_ASN_ENCODING, signedCRL, + sizeof(signedCRL), CERT_STORE_ADD_ALWAYS, &crl); + ok(res, "CertAddEncodedCRLToStore failed\n"); + + res = CertAddEncodedCTLToStore(store, X509_ASN_ENCODING, signedCTLWithCTLInnerContent, + sizeof(signedCTLWithCTLInnerContent), CERT_STORE_ADD_ALWAYS, &ctl); + ok(res, "CertAddEncodedCTLToStore failed\n"); + + CertFreeCertificateContext(cert); + CertFreeCRLContext(crl); + CertFreeCTLContext(ctl); + + res = CertCloseStore(store, CERT_CLOSE_STORE_CHECK_FLAG); + ok(res, "CertCloseStore failed\n"); } static void test_I_UpdateStore(void)