From: Paul Gofman pgofman@codeweavers.com
--- dlls/crypt32/context.c | 2 ++ dlls/crypt32/crypt32_private.h | 1 + dlls/crypt32/store.c | 55 ++++++++++++++++++++-------------- 3 files changed, 36 insertions(+), 22 deletions(-)
diff --git a/dlls/crypt32/context.c b/dlls/crypt32/context.c index 4a16d42296b..1a982f7bd0a 100644 --- a/dlls/crypt32/context.c +++ b/dlls/crypt32/context.c @@ -42,6 +42,7 @@ context_t *Context_CreateDataContext(size_t contextSize, const context_vtbl_t *v
context->vtbl = vtbl; context->ref = 1; + context->deleted_from_store = FALSE; context->linked = NULL;
store->vtbl->addref(store); @@ -64,6 +65,7 @@ context_t *Context_CreateLinkContext(unsigned int contextSize, context_t *linked memcpy(context_ptr(context), context_ptr(linked), contextSize); context->vtbl = linked->vtbl; context->ref = 1; + context->deleted_from_store = FALSE; context->linked = linked; context->properties = linked->properties; Context_AddRef(linked); diff --git a/dlls/crypt32/crypt32_private.h b/dlls/crypt32/crypt32_private.h index 9ac5b4a3067..6548dd36ab0 100644 --- a/dlls/crypt32/crypt32_private.h +++ b/dlls/crypt32/crypt32_private.h @@ -185,6 +185,7 @@ typedef struct { struct _context_t { const context_vtbl_t *vtbl; LONG ref; + BOOL deleted_from_store; struct WINE_CRYPTCERTSTORE *store; struct _context_t *linked; CONTEXT_PROPERTY_LIST *properties; diff --git a/dlls/crypt32/store.c b/dlls/crypt32/store.c index 97b745e661e..3291d0522b6 100644 --- a/dlls/crypt32/store.c +++ b/dlls/crypt32/store.c @@ -80,6 +80,8 @@ typedef struct _WINE_MEMSTORE { WINECRYPT_CERTSTORE hdr; CRITICAL_SECTION cs; + /* Objects are deleteted from the main list upon deleting from store and from _enum lists + * upon deleting objects themselves. */ struct list certs; struct list crls; struct list ctls; @@ -142,6 +144,14 @@ BOOL WINAPI I_CertUpdateStore(HCERTSTORE store1, HCERTSTORE store2, DWORD unk0,
static void memstore_free_context(context_t *context) { + WINE_MEMSTORE *store = (WINE_MEMSTORE *)context->store; + + TRACE(".\n"); + + EnterCriticalSection(&store->cs); + list_remove(&context->u.entry); + LeaveCriticalSection(&store->cs); + Context_Free(context); }
@@ -157,11 +167,8 @@ static BOOL MemStore_addContext(WINE_MEMSTORE *store, struct list *list, context TRACE("adding %p\n", context); EnterCriticalSection(&store->cs); if (existing) { - context->u.entry.prev = existing->u.entry.prev; - context->u.entry.next = existing->u.entry.next; - context->u.entry.prev->next = &context->u.entry; - context->u.entry.next->prev = &context->u.entry; - list_init(&existing->u.entry); + list_add_before(&existing->u.entry, &context->u.entry); + existing->deleted_from_store = TRUE; }else { list_add_head(list, &context->u.entry); } @@ -184,34 +191,37 @@ static context_t *MemStore_enumContext(WINE_MEMSTORE *store, struct list *list, next = list_next(list, &prev->u.entry); Context_Release(prev); }else { - next = list_next(list, list); + next = list_head(list); + } + + while (next) + { + ret = LIST_ENTRY(next, context_t, u.entry); + if (!ret->deleted_from_store) + break; + next = list_next(list, next); } + if (!next) + ret = NULL; LeaveCriticalSection(&store->cs);
- if (!next) { + if (!ret) { SetLastError(CRYPT_E_NOT_FOUND); return NULL; }
- ret = LIST_ENTRY(next, context_t, u.entry); Context_AddRef(ret); return ret; }
static BOOL MemStore_deleteContext(WINE_MEMSTORE *store, context_t *context) { - BOOL in_list = FALSE; - - EnterCriticalSection(&store->cs); - if (!list_empty(&context->u.entry)) { - list_remove(&context->u.entry); - list_init(&context->u.entry); - in_list = TRUE; + if (!context->deleted_from_store) + { + context->deleted_from_store = TRUE; + if (!context->ref) + memstore_free_context(context); } - LeaveCriticalSection(&store->cs); - - if(in_list && !context->ref) - memstore_free_context(context); return TRUE; }
@@ -223,14 +233,15 @@ static void free_contexts(struct list *list) { TRACE("freeing %p\n", context); list_remove(&context->u.entry); - memstore_free_context(context); + if (!context->deleted_from_store) + memstore_free_context(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)) + /* Free the context only if it is deleted from store. Otherwise it may be reused later. */ + if (context->deleted_from_store) memstore_free_context(context); }