From 976c6ff3f8fd679b70f3a92e3fa71c58256ec28f Mon Sep 17 00:00:00 2001 From: Juan Lang Date: Tue, 3 Nov 2009 17:04:32 -0800 Subject: [PATCH] crypt32: Correct reference counting when deleting contexts from collections. --- dlls/crypt32/collectionstore.c | 34 ++++++++++++++++++++++++++++------ dlls/crypt32/tests/store.c | 22 ++++++++++++++++++++++ 2 files changed, 50 insertions(+), 6 deletions(-) diff --git a/dlls/crypt32/collectionstore.c b/dlls/crypt32/collectionstore.c index 12eb7c3f7a..e55c1bf91d 100644 --- a/dlls/crypt32/collectionstore.c +++ b/dlls/crypt32/collectionstore.c @@ -255,11 +255,19 @@ static BOOL CRYPT_CollectionDeleteCert(PWINECRYPT_CERTSTORE store, void *pCertContext) { BOOL ret; + PCCERT_CONTEXT linked; TRACE("(%p, %p)\n", store, pCertContext); - ret = CertDeleteCertificateFromStore( - Context_GetLinkedContext(pCertContext, sizeof(CERT_CONTEXT))); + /* Deleting the linked context results in its ref count getting + * decreased, but the caller of this (CertDeleteCertificateFromStore) also + * decreases pCertContext's ref count, by calling + * CertFreeCertificateContext. Increase ref count of linked context to + * compensate. + */ + linked = Context_GetLinkedContext(pCertContext, sizeof(CERT_CONTEXT)); + CertDuplicateCertificateContext(linked); + ret = CertDeleteCertificateFromStore(linked); return ret; } @@ -333,11 +341,18 @@ static BOOL CRYPT_CollectionDeleteCRL(PWINECRYPT_CERTSTORE store, void *pCrlContext) { BOOL ret; + PCCRL_CONTEXT linked; TRACE("(%p, %p)\n", store, pCrlContext); - ret = CertDeleteCRLFromStore( - Context_GetLinkedContext(pCrlContext, sizeof(CRL_CONTEXT))); + /* Deleting the linked context results in its ref count getting + * decreased, but the caller of this (CertDeleteCRLFromStore) also + * decreases pCrlContext's ref count, by calling CertFreeCRLContext. + * Increase ref count of linked context to compensate. + */ + linked = Context_GetLinkedContext(pCrlContext, sizeof(CRL_CONTEXT)); + CertDuplicateCRLContext(linked); + ret = CertDeleteCRLFromStore(linked); return ret; } @@ -411,11 +426,18 @@ static BOOL CRYPT_CollectionDeleteCTL(PWINECRYPT_CERTSTORE store, void *pCtlContext) { BOOL ret; + PCCTL_CONTEXT linked; TRACE("(%p, %p)\n", store, pCtlContext); - ret = CertDeleteCTLFromStore( - Context_GetLinkedContext(pCtlContext, sizeof(CTL_CONTEXT))); + /* Deleting the linked context results in its ref count getting + * decreased, but the caller of this (CertDeleteCTLFromStore) also + * decreases pCtlContext's ref count, by calling CertFreeCTLContext. + * Increase ref count of linked context to compensate. + */ + linked = Context_GetLinkedContext(pCtlContext, sizeof(CTL_CONTEXT)); + CertDuplicateCTLContext(linked); + ret = CertDeleteCTLFromStore(linked); return ret; } diff --git a/dlls/crypt32/tests/store.c b/dlls/crypt32/tests/store.c index 88f53ed1e6..1f6609cf63 100644 --- a/dlls/crypt32/tests/store.c +++ b/dlls/crypt32/tests/store.c @@ -574,6 +574,28 @@ static void testCollectionStore(void) CertCloseStore(collection, 0); CertCloseStore(store2, 0); CertCloseStore(store1, 0); + + /* Test adding certificates to and deleting certificates from collections. + */ + store1 = CertOpenSystemStoreA(0, "My"); + collection = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0, + CERT_STORE_CREATE_NEW_FLAG, NULL); + + ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING, + bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, &context); + ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n", GetLastError()); + CertDeleteCertificateFromStore(context); + + CertAddStoreToCollection(collection, store1, + CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0); + + ret = CertAddEncodedCertificateToStore(collection, X509_ASN_ENCODING, + bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, &context); + ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n", GetLastError()); + CertDeleteCertificateFromStore(context); + + CertCloseStore(collection, 0); + CertCloseStore(store1, 0); } /* Looks for the property with ID propID in the buffer buf. Returns a pointer