Commit 0811851b authored by Juan Lang's avatar Juan Lang Committed by Alexandre Julliard

crypt32: Abstract contexts.

- create a base cert context, and make functions unaware whether they're dealing with the base or derived type - simplify stores as a result
parent 6f9dd397
...@@ -120,30 +120,19 @@ struct WINE_CRYPTCERTSTORE; ...@@ -120,30 +120,19 @@ struct WINE_CRYPTCERTSTORE;
typedef struct WINE_CRYPTCERTSTORE * (*StoreOpenFunc)(HCRYPTPROV hCryptProv, typedef struct WINE_CRYPTCERTSTORE * (*StoreOpenFunc)(HCRYPTPROV hCryptProv,
DWORD dwFlags, const void *pvPara); DWORD dwFlags, const void *pvPara);
struct _WINE_CERT_CONTEXT_REF;
/* Called to enumerate the next certificate in a store. The returned pointer
* must be newly allocated (via CryptMemAlloc): CertFreeCertificateContext
* frees it.
*/
typedef struct _WINE_CERT_CONTEXT_REF * (*EnumCertFunc)
(struct WINE_CRYPTCERTSTORE *store, struct _WINE_CERT_CONTEXT_REF *pPrev);
struct _WINE_CERT_CONTEXT; struct _WINE_CERT_CONTEXT;
/* Called to add a new certificate context to a store. The context does not /* Called to enumerate the next certificate in a store. */
* yet have a reference. If ppStoreContext is not NULL, a reference to the typedef struct _WINE_CERT_CONTEXT * (*EnumCertFunc)
* added context should be returned in *ppStoreContext. (struct WINE_CRYPTCERTSTORE *store, struct _WINE_CERT_CONTEXT *pPrev);
/* Called to add a new certificate context to a store. If ppStoreContext is
* not NULL, the added context should be returned in *ppStoreContext.
*/ */
typedef BOOL (*AddCertFunc)(struct WINE_CRYPTCERTSTORE *store, typedef BOOL (*AddCertFunc)(struct WINE_CRYPTCERTSTORE *store,
struct _WINE_CERT_CONTEXT *context, DWORD dwAddDisposition, struct _WINE_CERT_CONTEXT *context, DWORD dwAddDisposition,
PCCERT_CONTEXT *ppStoreContext); PCCERT_CONTEXT *ppStoreContext);
/* Optional, called when a cert context reference is being freed. Don't free
* the ref pointer itself, CertFreeCertificateContext does that.
*/
typedef void (*FreeCertFunc)(struct _WINE_CERT_CONTEXT_REF *ref);
typedef enum _CertStoreType { typedef enum _CertStoreType {
StoreTypeMem, StoreTypeMem,
StoreTypeCollection, StoreTypeCollection,
...@@ -168,40 +157,49 @@ typedef struct WINE_CRYPTCERTSTORE ...@@ -168,40 +157,49 @@ typedef struct WINE_CRYPTCERTSTORE
AddCertFunc addCert; AddCertFunc addCert;
EnumCertFunc enumCert; EnumCertFunc enumCert;
PFN_CERT_STORE_PROV_DELETE_CERT deleteCert; PFN_CERT_STORE_PROV_DELETE_CERT deleteCert;
FreeCertFunc freeCert; /* optional */
PFN_CERT_STORE_PROV_CONTROL control; /* optional */ PFN_CERT_STORE_PROV_CONTROL control; /* optional */
} WINECRYPT_CERTSTORE, *PWINECRYPT_CERTSTORE; } WINECRYPT_CERTSTORE, *PWINECRYPT_CERTSTORE;
/* A certificate context has pointers to data that are owned by this module, typedef enum _ContextType {
* so rather than duplicate the data every time a certificate context is ContextTypeData,
* copied, I keep a reference count to the data. Thus I have two data ContextTypeLink,
* structures, the "true" certificate context (that has the reference count) } ContextType;
* and a reference certificate context, that has a pointer to the true context.
* Each one can be cast to a PCERT_CONTEXT, though you'll usually be dealing /* A certificate context. This is the base type, and the two real types
* with the reference version. * (data and link) derive from it. Each one can be cast to a PCCERT_CONTEXT.
*/ */
typedef struct _WINE_CERT_CONTEXT typedef struct _WINE_CERT_CONTEXT
{ {
CERT_CONTEXT cert;
LONG ref;
ContextType type;
} WINE_CERT_CONTEXT, *PWINE_CERT_CONTEXT;
typedef const struct _WINE_CERT_CONTEXT PCWINE_CERT_CONTEXT;
typedef struct _WINE_CERT_CONTEXT_DATA
{
CERT_CONTEXT cert; CERT_CONTEXT cert;
LONG ref; LONG ref;
ContextType type; /* always ContextTypeData */
PCONTEXT_PROPERTY_LIST properties; PCONTEXT_PROPERTY_LIST properties;
} WINE_CERT_CONTEXT, *PWINE_CERT_CONTEXT; } WINE_CERT_CONTEXT_DATA, *PWINE_CERT_CONTEXT_DATA;
typedef const struct _WINE_CERT_CONTEXT PCWINE_CERT_CONTEXT; typedef const struct _WINE_CERT_CONTEXT_DATA PCWINE_CERT_CONTEXT_DATA;
typedef struct _WINE_CERT_CONTEXT_REF typedef struct _WINE_CERT_CONTEXT_LINK
{ {
CERT_CONTEXT cert; CERT_CONTEXT cert;
LONG ref; LONG ref;
PWINE_CERT_CONTEXT context; ContextType type; /* always ContextTypeLink */
} WINE_CERT_CONTEXT_REF, *PWINE_CERT_CONTEXT_REF; PWINE_CERT_CONTEXT linked;
typedef const struct _WINE_CERT_CONTEXT_REF PCWINE_CERT_CONTEXT_REF; } WINE_CERT_CONTEXT_LINK, *PWINE_CERT_CONTEXT_LINK;
typedef const struct _WINE_CERT_CONTEXT_LINK PCWINE_CERT_CONTEXT_LINK;
/* A mem store has a list of these. They're also returned by the mem store /* A mem store has a list of these. They're also returned by the mem store
* during enumeration. * during enumeration.
*/ */
typedef struct _WINE_CERT_LIST_ENTRY typedef struct _WINE_CERT_LIST_ENTRY
{ {
WINE_CERT_CONTEXT_REF cert; WINE_CERT_CONTEXT_LINK cert;
struct list entry; struct list entry;
} WINE_CERT_LIST_ENTRY, *PWINE_CERT_LIST_ENTRY; } WINE_CERT_LIST_ENTRY, *PWINE_CERT_LIST_ENTRY;
...@@ -218,13 +216,6 @@ typedef struct _WINE_HASH_TO_DELETE ...@@ -218,13 +216,6 @@ typedef struct _WINE_HASH_TO_DELETE
struct list entry; struct list entry;
} WINE_HASH_TO_DELETE, *PWINE_HASH_TO_DELETE; } WINE_HASH_TO_DELETE, *PWINE_HASH_TO_DELETE;
/* Returned by a provider store during enumeration. */
typedef struct _WINE_PROV_CERT_CONTEXT
{
WINE_CERT_CONTEXT_REF cert;
PWINE_CERT_CONTEXT_REF childContext;
} WINE_PROV_CERT_CONTEXT, *PWINE_PROV_CERT_CONTEXT;
typedef struct _WINE_REGSTOREINFO typedef struct _WINE_REGSTOREINFO
{ {
DWORD dwOpenFlags; DWORD dwOpenFlags;
...@@ -253,9 +244,8 @@ typedef struct _WINE_STORE_LIST_ENTRY ...@@ -253,9 +244,8 @@ typedef struct _WINE_STORE_LIST_ENTRY
*/ */
typedef struct _WINE_COLLECTION_CERT_CONTEXT typedef struct _WINE_COLLECTION_CERT_CONTEXT
{ {
WINE_CERT_CONTEXT_REF cert; WINE_CERT_CONTEXT_LINK cert;
PWINE_STORE_LIST_ENTRY storeEntry; PWINE_STORE_LIST_ENTRY storeEntry;
PWINE_CERT_CONTEXT_REF childContext;
} WINE_COLLECTION_CERT_CONTEXT, *PWINE_COLLECTION_CERT_CONTEXT; } WINE_COLLECTION_CERT_CONTEXT, *PWINE_COLLECTION_CERT_CONTEXT;
typedef struct _WINE_COLLECTIONSTORE typedef struct _WINE_COLLECTIONSTORE
...@@ -277,20 +267,23 @@ typedef struct _WINE_PROVIDERSTORE ...@@ -277,20 +267,23 @@ typedef struct _WINE_PROVIDERSTORE
PFN_CERT_STORE_PROV_CONTROL provControl; PFN_CERT_STORE_PROV_CONTROL provControl;
} WINE_PROVIDERSTORE, *PWINE_PROVIDERSTORE; } WINE_PROVIDERSTORE, *PWINE_PROVIDERSTORE;
/* Like CertGetCertificateContextProperty, but operates directly on the /* Internal version of CertGetCertificateContextProperty that gets properties
* WINE_CERT_CONTEXT. Doesn't support special-case properties, since they * directly from the context (or the context it's linked to, depending on its
* are handled by CertGetCertificateContextProperty, and are particular to the * type.) Doesn't handle special-case properties, since they are handled by
* store in which the property exists (which is separate from the context.) * CertGetCertificateContextProperty, and are particular to the store in which
* the property exists (which is separate from the context.)
*/ */
static BOOL WINAPI CRYPT_GetCertificateContextProperty( static BOOL WINAPI CRYPT_GetCertificateContextProperty(
PWINE_CERT_CONTEXT context, DWORD dwPropId, void *pvData, DWORD *pcbData); PWINE_CERT_CONTEXT context, DWORD dwPropId, void *pvData, DWORD *pcbData);
/* Like CertSetCertificateContextProperty, but operates directly on the /* Internal version of CertSetCertificateContextProperty that sets properties
* WINE_CERT_CONTEXT. Doesn't handle special cases, since they're handled by * directly on the context (or the context it's linked to, depending on its
* type.) Doesn't handle special cases, since they're handled by
* CertSetCertificateContextProperty anyway. * CertSetCertificateContextProperty anyway.
*/ */
static BOOL WINAPI CRYPT_SetCertificateContextProperty( static BOOL WINAPI CRYPT_SetCertificateContextProperty(
PWINE_CERT_CONTEXT context, DWORD dwPropId, DWORD dwFlags, const void *pvData); PWINE_CERT_CONTEXT context, DWORD dwPropId, DWORD dwFlags,
const void *pvData);
static void CRYPT_InitStore(WINECRYPT_CERTSTORE *store, HCRYPTPROV hCryptProv, static void CRYPT_InitStore(WINECRYPT_CERTSTORE *store, HCRYPTPROV hCryptProv,
DWORD dwFlags, CertStoreType type) DWORD dwFlags, CertStoreType type)
...@@ -307,34 +300,22 @@ static void CRYPT_InitStore(WINECRYPT_CERTSTORE *store, HCRYPTPROV hCryptProv, ...@@ -307,34 +300,22 @@ static void CRYPT_InitStore(WINECRYPT_CERTSTORE *store, HCRYPTPROV hCryptProv,
store->dwOpenFlags = dwFlags; store->dwOpenFlags = dwFlags;
} }
/* Initializes the reference ref to point to pCertContext, which is assumed to /* Initializes the reference ref to point to context, and increments context's
* be a PWINE_CERT_CONTEXT, and increments pCertContext's reference count. * reference count. Also sets the hCertStore member of the reference to store.
* Also sets the hCertStore member of the reference to store.
*/ */
static void CRYPT_InitCertRef(PWINE_CERT_CONTEXT_REF ref, static void CRYPT_InitCertRef(PWINE_CERT_CONTEXT_LINK ref,
PWINE_CERT_CONTEXT context, HCERTSTORE store) PWINE_CERT_CONTEXT context, HCERTSTORE store)
{ {
TRACE("(%p, %p)\n", ref, context); TRACE("(%p, %p)\n", ref, context);
memcpy(&ref->cert, context, sizeof(ref->cert)); memcpy(&ref->cert, context, sizeof(ref->cert));
ref->ref = 1; ref->ref = 1;
ref->context = context; ref->type = ContextTypeLink;
ref->linked = context;
InterlockedIncrement(&context->ref); InterlockedIncrement(&context->ref);
TRACE("%p's ref count is %ld\n", context, context->ref); TRACE("%p's ref count is %ld\n", context, context->ref);
ref->cert.hCertStore = store; ref->cert.hCertStore = store;
} }
static PWINE_CERT_CONTEXT_REF CRYPT_CreateCertRef(PWINE_CERT_CONTEXT context,
HCERTSTORE store)
{
PWINE_CERT_CONTEXT_REF pCertRef = CryptMemAlloc(
sizeof(WINE_CERT_CONTEXT_REF));
TRACE("(%p, %p)\n", context, store);
if (pCertRef)
CRYPT_InitCertRef(pCertRef, context, store);
return pCertRef;
}
static BOOL CRYPT_MemAddCert(PWINECRYPT_CERTSTORE store, static BOOL CRYPT_MemAddCert(PWINECRYPT_CERTSTORE store,
PWINE_CERT_CONTEXT cert, DWORD dwAddDisposition, PWINE_CERT_CONTEXT cert, DWORD dwAddDisposition,
PCCERT_CONTEXT *ppStoreContext) PCCERT_CONTEXT *ppStoreContext)
...@@ -350,8 +331,8 @@ static BOOL CRYPT_MemAddCert(PWINECRYPT_CERTSTORE store, ...@@ -350,8 +331,8 @@ static BOOL CRYPT_MemAddCert(PWINECRYPT_CERTSTORE store,
BYTE hashToAdd[20]; BYTE hashToAdd[20];
DWORD size = sizeof(hashToAdd); DWORD size = sizeof(hashToAdd);
ret = CRYPT_GetCertificateContextProperty(cert, CERT_HASH_PROP_ID, ret = CRYPT_GetCertificateContextProperty((PWINE_CERT_CONTEXT)cert,
hashToAdd, &size); CERT_HASH_PROP_ID, hashToAdd, &size);
if (ret) if (ret)
{ {
CRYPT_HASH_BLOB blob = { sizeof(hashToAdd), hashToAdd }; CRYPT_HASH_BLOB blob = { sizeof(hashToAdd), hashToAdd };
...@@ -402,7 +383,7 @@ static BOOL CRYPT_MemAddCert(PWINECRYPT_CERTSTORE store, ...@@ -402,7 +383,7 @@ static BOOL CRYPT_MemAddCert(PWINECRYPT_CERTSTORE store,
if (entry) if (entry)
{ {
TRACE("adding %p\n", entry); TRACE("adding %p\n", entry);
CRYPT_InitCertRef(&entry->cert, cert, store); CRYPT_InitCertRef(&entry->cert, (PWINE_CERT_CONTEXT)cert, store);
EnterCriticalSection(&ms->cs); EnterCriticalSection(&ms->cs);
list_add_tail(&ms->certs, &entry->entry); list_add_tail(&ms->certs, &entry->entry);
LeaveCriticalSection(&ms->cs); LeaveCriticalSection(&ms->cs);
...@@ -420,11 +401,12 @@ static BOOL CRYPT_MemAddCert(PWINECRYPT_CERTSTORE store, ...@@ -420,11 +401,12 @@ static BOOL CRYPT_MemAddCert(PWINECRYPT_CERTSTORE store,
return ret; return ret;
} }
static PWINE_CERT_CONTEXT_REF CRYPT_MemEnumCert(PWINECRYPT_CERTSTORE store, static PWINE_CERT_CONTEXT CRYPT_MemEnumCert(PWINECRYPT_CERTSTORE store,
PWINE_CERT_CONTEXT_REF pPrev) PWINE_CERT_CONTEXT pPrev)
{ {
WINE_MEMSTORE *ms = (WINE_MEMSTORE *)store; WINE_MEMSTORE *ms = (WINE_MEMSTORE *)store;
PWINE_CERT_LIST_ENTRY prevEntry = (PWINE_CERT_LIST_ENTRY)pPrev, ret; PWINE_CERT_LIST_ENTRY prevEntry = (PWINE_CERT_LIST_ENTRY)pPrev;
PWINE_CERT_CONTEXT ret;
struct list *listNext; struct list *listNext;
TRACE("(%p, %p)\n", store, pPrev); TRACE("(%p, %p)\n", store, pPrev);
...@@ -437,15 +419,8 @@ static PWINE_CERT_CONTEXT_REF CRYPT_MemEnumCert(PWINECRYPT_CERTSTORE store, ...@@ -437,15 +419,8 @@ static PWINE_CERT_CONTEXT_REF CRYPT_MemEnumCert(PWINECRYPT_CERTSTORE store,
else else
listNext = list_next(&ms->certs, &ms->certs); listNext = list_next(&ms->certs, &ms->certs);
if (listNext) if (listNext)
{ ret = (PWINE_CERT_CONTEXT)CertDuplicateCertificateContext(
ret = CryptMemAlloc(sizeof(WINE_CERT_LIST_ENTRY)); (PCCERT_CONTEXT)LIST_ENTRY(listNext, WINE_CERT_LIST_ENTRY, entry));
if (ret)
{
memcpy(ret, LIST_ENTRY(listNext, WINE_CERT_LIST_ENTRY, entry),
sizeof(WINE_CERT_LIST_ENTRY));
InterlockedIncrement(&ret->cert.context->ref);
}
}
else else
{ {
SetLastError(CRYPT_E_NOT_FOUND); SetLastError(CRYPT_E_NOT_FOUND);
...@@ -454,38 +429,20 @@ static PWINE_CERT_CONTEXT_REF CRYPT_MemEnumCert(PWINECRYPT_CERTSTORE store, ...@@ -454,38 +429,20 @@ static PWINE_CERT_CONTEXT_REF CRYPT_MemEnumCert(PWINECRYPT_CERTSTORE store,
LeaveCriticalSection(&ms->cs); LeaveCriticalSection(&ms->cs);
TRACE("returning %p\n", ret); TRACE("returning %p\n", ret);
return (PWINE_CERT_CONTEXT_REF)ret; return ret;
} }
static BOOL WINAPI CRYPT_MemDeleteCert(HCERTSTORE hCertStore, static BOOL WINAPI CRYPT_MemDeleteCert(HCERTSTORE hCertStore,
PCCERT_CONTEXT pCertContext, DWORD dwFlags) PCCERT_CONTEXT pCertContext, DWORD dwFlags)
{ {
WINE_MEMSTORE *store = (WINE_MEMSTORE *)hCertStore; WINE_MEMSTORE *store = (WINE_MEMSTORE *)hCertStore;
WINE_CERT_CONTEXT_REF *ref = (WINE_CERT_CONTEXT_REF *)pCertContext; PWINE_CERT_LIST_ENTRY cert = (PWINE_CERT_LIST_ENTRY)pCertContext;
PWINE_CERT_LIST_ENTRY cert, next; BOOL ret;
BOOL ret = TRUE;
/* Find the entry associated with the passed-in context, since the /* The passed-in context is itself a list entry, so just remove it. */
* passed-in context may not be a list entry itself (e.g. if it came from
* CertDuplicateCertificateContext.) Pointing to the same context is
* a sufficient test of equality.
*/
EnterCriticalSection(&store->cs); EnterCriticalSection(&store->cs);
LIST_FOR_EACH_ENTRY_SAFE(cert, next, &store->certs, WINE_CERT_LIST_ENTRY, list_remove(&cert->entry);
entry) ret = CertFreeCertificateContext(pCertContext);
{
if (cert->cert.context == ref->context)
{
TRACE("removing %p\n", cert);
/* FIXME: this isn't entirely thread-safe, the entry itself isn't
* protected.
*/
list_remove(&cert->entry);
cert->entry.prev = cert->entry.next = &store->certs;
ret = CertFreeCertificateContext((PCCERT_CONTEXT)cert);
break;
}
}
LeaveCriticalSection(&store->cs); LeaveCriticalSection(&store->cs);
return ret; return ret;
} }
...@@ -495,11 +452,6 @@ static void CRYPT_MemEmptyStore(PWINE_MEMSTORE store) ...@@ -495,11 +452,6 @@ static void CRYPT_MemEmptyStore(PWINE_MEMSTORE store)
PWINE_CERT_LIST_ENTRY cert, next; PWINE_CERT_LIST_ENTRY cert, next;
EnterCriticalSection(&store->cs); EnterCriticalSection(&store->cs);
/* Note that CertFreeCertificateContext calls CryptMemFree on the passed-in
* pointer if its ref-count reaches zero. That's okay here because there
* aren't any allocated data outside of the WINE_CERT_CONTEXT_REF portion
* of the CertListEntry.
*/
LIST_FOR_EACH_ENTRY_SAFE(cert, next, &store->certs, WINE_CERT_LIST_ENTRY, LIST_FOR_EACH_ENTRY_SAFE(cert, next, &store->certs, WINE_CERT_LIST_ENTRY,
entry) entry)
{ {
...@@ -581,22 +533,6 @@ static BOOL CRYPT_CollectionAddCert(PWINECRYPT_CERTSTORE store, ...@@ -581,22 +533,6 @@ static BOOL CRYPT_CollectionAddCert(PWINECRYPT_CERTSTORE store,
return ret; return ret;
} }
static PWINE_CERT_CONTEXT_REF CRYPT_CollectionCreateCertRef(
PWINE_CERT_CONTEXT context, HCERTSTORE store)
{
PWINE_COLLECTION_CERT_CONTEXT ret = CryptMemAlloc(
sizeof(WINE_COLLECTION_CERT_CONTEXT));
if (ret)
{
/* Initialize to empty for now, just make sure the size is right */
CRYPT_InitCertRef((PWINE_CERT_CONTEXT_REF)ret, context, store);
ret->storeEntry = NULL;
ret->childContext = NULL;
}
return (PWINE_CERT_CONTEXT_REF)ret;
}
static void WINAPI CRYPT_CollectionCloseStore(HCERTSTORE store, DWORD dwFlags) static void WINAPI CRYPT_CollectionCloseStore(HCERTSTORE store, DWORD dwFlags)
{ {
PWINE_COLLECTIONSTORE cs = (PWINE_COLLECTIONSTORE)store; PWINE_COLLECTIONSTORE cs = (PWINE_COLLECTIONSTORE)store;
...@@ -629,27 +565,40 @@ static PWINE_COLLECTION_CERT_CONTEXT CRYPT_CollectionAdvanceEnum( ...@@ -629,27 +565,40 @@ static PWINE_COLLECTION_CERT_CONTEXT CRYPT_CollectionAdvanceEnum(
PWINE_COLLECTION_CERT_CONTEXT pPrev) PWINE_COLLECTION_CERT_CONTEXT pPrev)
{ {
PWINE_COLLECTION_CERT_CONTEXT ret; PWINE_COLLECTION_CERT_CONTEXT ret;
PWINE_CERT_CONTEXT_REF child; PWINE_CERT_CONTEXT child;
struct list *storeNext = list_next(&store->stores, &storeEntry->entry); struct list *storeNext = list_next(&store->stores, &storeEntry->entry);
TRACE("(%p, %p, %p)\n", store, storeEntry, pPrev); TRACE("(%p, %p, %p)\n", store, storeEntry, pPrev);
child = storeEntry->store->enumCert((HCERTSTORE)storeEntry->store,
pPrev ? pPrev->childContext : NULL);
if (pPrev) if (pPrev)
{ {
pPrev->childContext = NULL; /* Ref-counting funny business: "duplicate" (addref) the child, because
* the CertFreeCertificateContext(pPrev) below can cause the ref count
* to become negative. See comment below as well.
*/
child = ((PWINE_COLLECTION_CERT_CONTEXT)pPrev)->cert.linked;
CertDuplicateCertificateContext((PCCERT_CONTEXT)child);
child = storeEntry->store->enumCert((HCERTSTORE)storeEntry->store,
child);
CertFreeCertificateContext((PCCERT_CONTEXT)pPrev); CertFreeCertificateContext((PCCERT_CONTEXT)pPrev);
pPrev = NULL; pPrev = NULL;
} }
else
child = storeEntry->store->enumCert((HCERTSTORE)storeEntry->store,
NULL);
if (child) if (child)
{ {
ret = (PWINE_COLLECTION_CERT_CONTEXT)CRYPT_CollectionCreateCertRef( ret = CryptMemAlloc(sizeof(WINE_COLLECTION_CERT_CONTEXT));
child->context, store);
if (ret) if (ret)
{ {
CRYPT_InitCertRef((PWINE_CERT_CONTEXT_LINK)ret, child, store);
/* enumCert already addref'd once, and CRYPT_InitCertRef does again,
* so free child once to get the ref count right. (Not doing so
* will leak memory if the caller calls CertFreeCertificateContext
* rather than CertEnumCertificatesInStore.)
*/
CertFreeCertificateContext((PCCERT_CONTEXT)child);
ret->storeEntry = storeEntry; ret->storeEntry = storeEntry;
ret->childContext = child;
} }
else else
CertFreeCertificateContext((PCCERT_CONTEXT)child); CertFreeCertificateContext((PCCERT_CONTEXT)child);
...@@ -671,8 +620,8 @@ static PWINE_COLLECTION_CERT_CONTEXT CRYPT_CollectionAdvanceEnum( ...@@ -671,8 +620,8 @@ static PWINE_COLLECTION_CERT_CONTEXT CRYPT_CollectionAdvanceEnum(
return ret; return ret;
} }
static PWINE_CERT_CONTEXT_REF CRYPT_CollectionEnumCert( static PWINE_CERT_CONTEXT CRYPT_CollectionEnumCert(PWINECRYPT_CERTSTORE store,
PWINECRYPT_CERTSTORE store, PWINE_CERT_CONTEXT_REF pPrev) PWINE_CERT_CONTEXT pPrev)
{ {
PWINE_COLLECTIONSTORE cs = (PWINE_COLLECTIONSTORE)store; PWINE_COLLECTIONSTORE cs = (PWINE_COLLECTIONSTORE)store;
PWINE_COLLECTION_CERT_CONTEXT prevEntry = PWINE_COLLECTION_CERT_CONTEXT prevEntry =
...@@ -705,7 +654,7 @@ static PWINE_CERT_CONTEXT_REF CRYPT_CollectionEnumCert( ...@@ -705,7 +654,7 @@ static PWINE_CERT_CONTEXT_REF CRYPT_CollectionEnumCert(
LeaveCriticalSection(&cs->cs); LeaveCriticalSection(&cs->cs);
} }
TRACE("returning %p\n", ret); TRACE("returning %p\n", ret);
return (PWINE_CERT_CONTEXT_REF)ret; return (PWINE_CERT_CONTEXT)ret;
} }
static BOOL WINAPI CRYPT_CollectionDeleteCert(HCERTSTORE hCertStore, static BOOL WINAPI CRYPT_CollectionDeleteCert(HCERTSTORE hCertStore,
...@@ -717,22 +666,10 @@ static BOOL WINAPI CRYPT_CollectionDeleteCert(HCERTSTORE hCertStore, ...@@ -717,22 +666,10 @@ static BOOL WINAPI CRYPT_CollectionDeleteCert(HCERTSTORE hCertStore,
TRACE("(%p, %p, %08lx)\n", hCertStore, pCertContext, dwFlags); TRACE("(%p, %p, %08lx)\n", hCertStore, pCertContext, dwFlags);
ret = CertDeleteCertificateFromStore((PCCERT_CONTEXT)context->childContext); ret = CertDeleteCertificateFromStore((PCCERT_CONTEXT)context->cert.linked);
if (ret)
context->childContext = NULL;
return ret; return ret;
} }
static void CRYPT_CollectionFreeCert(PWINE_CERT_CONTEXT_REF ref)
{
PWINE_COLLECTION_CERT_CONTEXT context = (PWINE_COLLECTION_CERT_CONTEXT)ref;
TRACE("(%p)\n", ref);
if (context->childContext)
CertFreeCertificateContext((PCCERT_CONTEXT)context->childContext);
}
static WINECRYPT_CERTSTORE *CRYPT_CollectionOpenStore(HCRYPTPROV hCryptProv, static WINECRYPT_CERTSTORE *CRYPT_CollectionOpenStore(HCRYPTPROV hCryptProv,
DWORD dwFlags, const void *pvPara) DWORD dwFlags, const void *pvPara)
{ {
...@@ -755,7 +692,6 @@ static WINECRYPT_CERTSTORE *CRYPT_CollectionOpenStore(HCRYPTPROV hCryptProv, ...@@ -755,7 +692,6 @@ static WINECRYPT_CERTSTORE *CRYPT_CollectionOpenStore(HCRYPTPROV hCryptProv,
store->hdr.addCert = CRYPT_CollectionAddCert; store->hdr.addCert = CRYPT_CollectionAddCert;
store->hdr.enumCert = CRYPT_CollectionEnumCert; store->hdr.enumCert = CRYPT_CollectionEnumCert;
store->hdr.deleteCert = CRYPT_CollectionDeleteCert; store->hdr.deleteCert = CRYPT_CollectionDeleteCert;
store->hdr.freeCert = CRYPT_CollectionFreeCert;
InitializeCriticalSection(&store->cs); InitializeCriticalSection(&store->cs);
list_init(&store->stores); list_init(&store->stores);
} }
...@@ -797,52 +733,34 @@ static BOOL CRYPT_ProvAddCert(PWINECRYPT_CERTSTORE store, ...@@ -797,52 +733,34 @@ static BOOL CRYPT_ProvAddCert(PWINECRYPT_CERTSTORE store,
ret = ps->provWriteCert(ps->hStoreProv, (PCCERT_CONTEXT)cert, ret = ps->provWriteCert(ps->hStoreProv, (PCCERT_CONTEXT)cert,
CERT_STORE_PROV_WRITE_ADD_FLAG); CERT_STORE_PROV_WRITE_ADD_FLAG);
if (ret) if (ret)
{
ret = ps->memStore->addCert(ps->memStore, cert, ret = ps->memStore->addCert(ps->memStore, cert,
dwAddDisposition, ppStoreContext); dwAddDisposition, ppStoreContext);
/* dirty trick: replace the returned context's hCertStore with
* store.
*/
if (ppStoreContext)
(*(PCERT_CONTEXT *)ppStoreContext)->hCertStore = store;
}
} }
return ret; return ret;
} }
static PWINE_CERT_CONTEXT_REF CRYPT_ProvCreateCertRef( static PWINE_CERT_CONTEXT CRYPT_ProvEnumCert(PWINECRYPT_CERTSTORE store,
PWINE_CERT_CONTEXT context, HCERTSTORE store) PWINE_CERT_CONTEXT pPrev)
{
PWINE_PROV_CERT_CONTEXT ret = CryptMemAlloc(sizeof(WINE_PROV_CERT_CONTEXT));
if (ret)
{
CRYPT_InitCertRef((PWINE_CERT_CONTEXT_REF)ret, context, store);
ret->childContext = NULL;
}
return (PWINE_CERT_CONTEXT_REF)ret;
}
static PWINE_CERT_CONTEXT_REF CRYPT_ProvEnumCert(PWINECRYPT_CERTSTORE store,
PWINE_CERT_CONTEXT_REF pPrev)
{ {
PWINE_PROVIDERSTORE ps = (PWINE_PROVIDERSTORE)store; PWINE_PROVIDERSTORE ps = (PWINE_PROVIDERSTORE)store;
PWINE_CERT_CONTEXT_REF child; PWINE_CERT_CONTEXT ret;
PWINE_PROV_CERT_CONTEXT prev = (PWINE_PROV_CERT_CONTEXT)pPrev, ret = NULL;
TRACE("(%p, %p)\n", store, pPrev);
child = ps->memStore->enumCert(ps->memStore, prev ? prev->childContext ret = ps->memStore->enumCert(ps->memStore, pPrev);
: NULL); if (ret)
if (prev)
{
prev->childContext = NULL;
CertFreeCertificateContext((PCCERT_CONTEXT)prev);
prev = NULL;
}
if (child)
{ {
ret = (PWINE_PROV_CERT_CONTEXT)CRYPT_ProvCreateCertRef(child->context, /* same dirty trick: replace the returned context's hCertStore with
store); * store.
if (ret) */
ret->childContext = child; ret->cert.hCertStore = store;
else
CertFreeCertificateContext((PCCERT_CONTEXT)child);
} }
return (PWINE_CERT_CONTEXT_REF)ret; return ret;
} }
static BOOL WINAPI CRYPT_ProvDeleteCert(HCERTSTORE hCertStore, static BOOL WINAPI CRYPT_ProvDeleteCert(HCERTSTORE hCertStore,
...@@ -860,16 +778,6 @@ static BOOL WINAPI CRYPT_ProvDeleteCert(HCERTSTORE hCertStore, ...@@ -860,16 +778,6 @@ static BOOL WINAPI CRYPT_ProvDeleteCert(HCERTSTORE hCertStore,
return ret; return ret;
} }
static void CRYPT_ProvFreeCert(PWINE_CERT_CONTEXT_REF ref)
{
PWINE_PROV_CERT_CONTEXT context = (PWINE_PROV_CERT_CONTEXT)ref;
TRACE("(%p)\n", ref);
if (context->childContext)
CertFreeCertificateContext((PCCERT_CONTEXT)context->childContext);
}
static BOOL WINAPI CRYPT_ProvControl(HCERTSTORE hCertStore, DWORD dwFlags, static BOOL WINAPI CRYPT_ProvControl(HCERTSTORE hCertStore, DWORD dwFlags,
DWORD dwCtrlType, void const *pvCtrlPara) DWORD dwCtrlType, void const *pvCtrlPara)
{ {
...@@ -908,7 +816,6 @@ static PWINECRYPT_CERTSTORE CRYPT_ProvCreateStore(HCRYPTPROV hCryptProv, ...@@ -908,7 +816,6 @@ static PWINECRYPT_CERTSTORE CRYPT_ProvCreateStore(HCRYPTPROV hCryptProv,
ret->hdr.addCert = CRYPT_ProvAddCert; ret->hdr.addCert = CRYPT_ProvAddCert;
ret->hdr.enumCert = CRYPT_ProvEnumCert; ret->hdr.enumCert = CRYPT_ProvEnumCert;
ret->hdr.deleteCert = CRYPT_ProvDeleteCert; ret->hdr.deleteCert = CRYPT_ProvDeleteCert;
ret->hdr.freeCert = CRYPT_ProvFreeCert;
ret->hdr.control = CRYPT_ProvControl; ret->hdr.control = CRYPT_ProvControl;
if (pProvInfo->cStoreProvFunc > CERT_STORE_PROV_CLOSE_FUNC) if (pProvInfo->cStoreProvFunc > CERT_STORE_PROV_CLOSE_FUNC)
ret->provCloseStore = ret->provCloseStore =
...@@ -1240,6 +1147,8 @@ static BOOL CRYPT_RegFlushStore(PWINE_REGSTOREINFO store, BOOL force) ...@@ -1240,6 +1147,8 @@ static BOOL CRYPT_RegFlushStore(PWINE_REGSTOREINFO store, BOOL force)
{ {
BOOL ret; BOOL ret;
TRACE("(%p, %d)\n", store, force);
if (store->dirty || force) if (store->dirty || force)
ret = CRYPT_RegWriteToReg(store); ret = CRYPT_RegWriteToReg(store);
else else
...@@ -1305,13 +1214,15 @@ static BOOL WINAPI CRYPT_RegDeleteCert(HCERTSTORE hCertStore, ...@@ -1305,13 +1214,15 @@ static BOOL WINAPI CRYPT_RegDeleteCert(HCERTSTORE hCertStore,
CERT_HASH_PROP_ID, toDelete->hash, &size); CERT_HASH_PROP_ID, toDelete->hash, &size);
if (ret) if (ret)
{ {
list_init(&toDelete->entry);
EnterCriticalSection(&store->cs); EnterCriticalSection(&store->cs);
list_add_tail(&store->certsToDelete, &toDelete->entry); list_add_tail(&store->certsToDelete, &toDelete->entry);
LeaveCriticalSection(&store->cs); LeaveCriticalSection(&store->cs);
} }
else else
{
CryptMemFree(toDelete); CryptMemFree(toDelete);
ret = FALSE;
}
} }
else else
ret = FALSE; ret = FALSE;
...@@ -1327,6 +1238,9 @@ static BOOL WINAPI CRYPT_RegControl(HCERTSTORE hCertStore, DWORD dwFlags, ...@@ -1327,6 +1238,9 @@ static BOOL WINAPI CRYPT_RegControl(HCERTSTORE hCertStore, DWORD dwFlags,
PWINE_REGSTOREINFO store = (PWINE_REGSTOREINFO)hCertStore; PWINE_REGSTOREINFO store = (PWINE_REGSTOREINFO)hCertStore;
BOOL ret; BOOL ret;
TRACE("(%p, %08lx, %ld, %p)\n", hCertStore, dwFlags, dwCtrlType,
pvCtrlPara);
switch (dwCtrlType) switch (dwCtrlType)
{ {
case CERT_STORE_CTRL_RESYNC: case CERT_STORE_CTRL_RESYNC:
...@@ -1840,13 +1754,11 @@ PCCRL_CONTEXT WINAPI CertCreateCRLContext( DWORD dwCertEncodingType, ...@@ -1840,13 +1754,11 @@ PCCRL_CONTEXT WINAPI CertCreateCRLContext( DWORD dwCertEncodingType,
} }
/* Decodes the encoded certificate and creates the certificate context for it. /* Decodes the encoded certificate and creates the certificate context for it.
* The reference count is initially zero, so you must create a reference to it
* to avoid leaking memory.
*/ */
static PWINE_CERT_CONTEXT CRYPT_CreateCertificateContext( static PWINE_CERT_CONTEXT CRYPT_CreateCertificateContext(
DWORD dwCertEncodingType, const BYTE *pbCertEncoded, DWORD cbCertEncoded) DWORD dwCertEncodingType, const BYTE *pbCertEncoded, DWORD cbCertEncoded)
{ {
PWINE_CERT_CONTEXT cert = NULL; PWINE_CERT_CONTEXT_DATA cert = NULL;
BOOL ret; BOOL ret;
PCERT_SIGNED_CONTENT_INFO signedCert = NULL; PCERT_SIGNED_CONTENT_INFO signedCert = NULL;
PCERT_INFO certInfo = NULL; PCERT_INFO certInfo = NULL;
...@@ -1879,7 +1791,7 @@ static PWINE_CERT_CONTEXT CRYPT_CreateCertificateContext( ...@@ -1879,7 +1791,7 @@ static PWINE_CERT_CONTEXT CRYPT_CreateCertificateContext(
{ {
BYTE *data = NULL; BYTE *data = NULL;
cert = CryptMemAlloc(sizeof(WINE_CERT_CONTEXT)); cert = CryptMemAlloc(sizeof(WINE_CERT_CONTEXT_DATA));
if (!cert) if (!cert)
goto end; goto end;
data = CryptMemAlloc(cbCertEncoded); data = CryptMemAlloc(cbCertEncoded);
...@@ -1895,46 +1807,57 @@ static PWINE_CERT_CONTEXT CRYPT_CreateCertificateContext( ...@@ -1895,46 +1807,57 @@ static PWINE_CERT_CONTEXT CRYPT_CreateCertificateContext(
cert->cert.cbCertEncoded = cbCertEncoded; cert->cert.cbCertEncoded = cbCertEncoded;
cert->cert.pCertInfo = certInfo; cert->cert.pCertInfo = certInfo;
cert->cert.hCertStore = 0; cert->cert.hCertStore = 0;
cert->ref = 0; cert->ref = 1;
cert->type = ContextTypeData;
cert->properties = ContextPropertyList_Create(); cert->properties = ContextPropertyList_Create();
} }
end: end:
return cert; return (PWINE_CERT_CONTEXT)cert;
}
static void CRYPT_FreeCert(PWINE_CERT_CONTEXT context)
{
CryptMemFree(context->cert.pbCertEncoded);
LocalFree(context->cert.pCertInfo);
ContextPropertyList_Free(context->properties);
CryptMemFree(context);
} }
PCCERT_CONTEXT WINAPI CertCreateCertificateContext(DWORD dwCertEncodingType, PCCERT_CONTEXT WINAPI CertCreateCertificateContext(DWORD dwCertEncodingType,
const BYTE *pbCertEncoded, DWORD cbCertEncoded) const BYTE *pbCertEncoded, DWORD cbCertEncoded)
{ {
PWINE_CERT_CONTEXT cert; PWINE_CERT_CONTEXT cert;
PWINE_CERT_CONTEXT_REF ret = NULL;
TRACE("(%08lx, %p, %ld)\n", dwCertEncodingType, pbCertEncoded, TRACE("(%08lx, %p, %ld)\n", dwCertEncodingType, pbCertEncoded,
cbCertEncoded); cbCertEncoded);
cert = CRYPT_CreateCertificateContext(dwCertEncodingType, pbCertEncoded, cert = CRYPT_CreateCertificateContext(dwCertEncodingType, pbCertEncoded,
cbCertEncoded); cbCertEncoded);
if (cert) return (PCCERT_CONTEXT)cert;
ret = CRYPT_CreateCertRef(cert, 0); }
return (PCCERT_CONTEXT)ret;
/* If context is a link, follows it to its linked context (recursively, if
* necessary) and returns the data context associated with the link.
* Otherwise just returns context.
*/
static inline PWINE_CERT_CONTEXT_DATA CertContext_GetDataContext(
PWINE_CERT_CONTEXT context)
{
PWINE_CERT_CONTEXT ptr = context;
while (ptr && ptr->type == ContextTypeLink)
ptr = ((PWINE_CERT_CONTEXT_LINK)ptr)->linked;
return (ptr && ptr->type == ContextTypeData) ?
(PWINE_CERT_CONTEXT_DATA)ptr : NULL;
} }
DWORD WINAPI CertEnumCertificateContextProperties(PCCERT_CONTEXT pCertContext, DWORD WINAPI CertEnumCertificateContextProperties(PCCERT_CONTEXT pCertContext,
DWORD dwPropId) DWORD dwPropId)
{ {
PWINE_CERT_CONTEXT_REF ref = (PWINE_CERT_CONTEXT_REF)pCertContext; PWINE_CERT_CONTEXT_DATA linked = CertContext_GetDataContext(
(PWINE_CERT_CONTEXT)pCertContext);
DWORD ret;
TRACE("(%p, %ld)\n", pCertContext, dwPropId); TRACE("(%p, %ld)\n", pCertContext, dwPropId);
return ContextPropertyList_EnumPropIDs(ref->context->properties, dwPropId); if (linked)
ret = ContextPropertyList_EnumPropIDs(linked->properties, dwPropId);
else
ret = 0;
return ret;
} }
static BOOL CRYPT_GetCertHashProp(PWINE_CERT_CONTEXT context, DWORD dwPropId, static BOOL CRYPT_GetCertHashProp(PWINE_CERT_CONTEXT context, DWORD dwPropId,
...@@ -1956,13 +1879,17 @@ static BOOL CRYPT_GetCertHashProp(PWINE_CERT_CONTEXT context, DWORD dwPropId, ...@@ -1956,13 +1879,17 @@ static BOOL CRYPT_GetCertHashProp(PWINE_CERT_CONTEXT context, DWORD dwPropId,
static BOOL WINAPI CRYPT_GetCertificateContextProperty( static BOOL WINAPI CRYPT_GetCertificateContextProperty(
PWINE_CERT_CONTEXT context, DWORD dwPropId, void *pvData, DWORD *pcbData) PWINE_CERT_CONTEXT context, DWORD dwPropId, void *pvData, DWORD *pcbData)
{ {
PWINE_CERT_CONTEXT_DATA linked = CertContext_GetDataContext(context);
BOOL ret; BOOL ret;
CRYPT_DATA_BLOB blob; CRYPT_DATA_BLOB blob;
TRACE("(%p, %ld, %p, %p)\n", context, dwPropId, pvData, pcbData); TRACE("(%p, %ld, %p, %p)\n", context, dwPropId, pvData, pcbData);
ret = ContextPropertyList_FindProperty(context->properties, dwPropId, if (linked)
&blob); ret = ContextPropertyList_FindProperty(linked->properties, dwPropId,
&blob);
else
ret = FALSE;
if (ret) if (ret)
{ {
if (!pvData) if (!pvData)
...@@ -2025,7 +1952,6 @@ static BOOL WINAPI CRYPT_GetCertificateContextProperty( ...@@ -2025,7 +1952,6 @@ static BOOL WINAPI CRYPT_GetCertificateContextProperty(
BOOL WINAPI CertGetCertificateContextProperty(PCCERT_CONTEXT pCertContext, BOOL WINAPI CertGetCertificateContextProperty(PCCERT_CONTEXT pCertContext,
DWORD dwPropId, void *pvData, DWORD *pcbData) DWORD dwPropId, void *pvData, DWORD *pcbData)
{ {
PWINE_CERT_CONTEXT_REF ref = (PWINE_CERT_CONTEXT_REF)pCertContext;
BOOL ret; BOOL ret;
TRACE("(%p, %ld, %p, %p)\n", pCertContext, dwPropId, pvData, pcbData); TRACE("(%p, %ld, %p, %p)\n", pCertContext, dwPropId, pvData, pcbData);
...@@ -2069,8 +1995,8 @@ BOOL WINAPI CertGetCertificateContextProperty(PCCERT_CONTEXT pCertContext, ...@@ -2069,8 +1995,8 @@ BOOL WINAPI CertGetCertificateContextProperty(PCCERT_CONTEXT pCertContext,
} }
} }
ret = CRYPT_GetCertificateContextProperty(ref->context, dwPropId, ret = CRYPT_GetCertificateContextProperty((PWINE_CERT_CONTEXT)pCertContext,
pvData, pcbData); dwPropId, pvData, pcbData);
TRACE("returning %d\n", ret); TRACE("returning %d\n", ret);
return ret; return ret;
} }
...@@ -2078,13 +2004,16 @@ BOOL WINAPI CertGetCertificateContextProperty(PCCERT_CONTEXT pCertContext, ...@@ -2078,13 +2004,16 @@ BOOL WINAPI CertGetCertificateContextProperty(PCCERT_CONTEXT pCertContext,
static BOOL WINAPI CRYPT_SetCertificateContextProperty( static BOOL WINAPI CRYPT_SetCertificateContextProperty(
PWINE_CERT_CONTEXT context, DWORD dwPropId, DWORD dwFlags, const void *pvData) PWINE_CERT_CONTEXT context, DWORD dwPropId, DWORD dwFlags, const void *pvData)
{ {
BOOL ret = FALSE; PWINE_CERT_CONTEXT_DATA linked = CertContext_GetDataContext(context);
BOOL ret;
TRACE("(%p, %ld, %08lx, %p)\n", context, dwPropId, dwFlags, pvData); TRACE("(%p, %ld, %08lx, %p)\n", context, dwPropId, dwFlags, pvData);
if (!pvData) if (!linked)
ret = FALSE;
else if (!pvData)
{ {
ContextPropertyList_RemoveProperty(context->properties, dwPropId); ContextPropertyList_RemoveProperty(linked->properties, dwPropId);
ret = TRUE; ret = TRUE;
} }
else else
...@@ -2111,16 +2040,17 @@ static BOOL WINAPI CRYPT_SetCertificateContextProperty( ...@@ -2111,16 +2040,17 @@ static BOOL WINAPI CRYPT_SetCertificateContextProperty(
{ {
PCRYPT_DATA_BLOB blob = (PCRYPT_DATA_BLOB)pvData; PCRYPT_DATA_BLOB blob = (PCRYPT_DATA_BLOB)pvData;
ret = ContextPropertyList_SetProperty(context->properties, dwPropId, ret = ContextPropertyList_SetProperty(linked->properties, dwPropId,
blob->pbData, blob->cbData); blob->pbData, blob->cbData);
break; break;
} }
case CERT_DATE_STAMP_PROP_ID: case CERT_DATE_STAMP_PROP_ID:
ret = ContextPropertyList_SetProperty(context->properties, dwPropId, ret = ContextPropertyList_SetProperty(linked->properties, dwPropId,
pvData, sizeof(FILETIME)); pvData, sizeof(FILETIME));
break; break;
default: default:
FIXME("%ld: stub\n", dwPropId); FIXME("%ld: stub\n", dwPropId);
ret = FALSE;
} }
} }
TRACE("returning %d\n", ret); TRACE("returning %d\n", ret);
...@@ -2130,7 +2060,6 @@ static BOOL WINAPI CRYPT_SetCertificateContextProperty( ...@@ -2130,7 +2060,6 @@ static BOOL WINAPI CRYPT_SetCertificateContextProperty(
BOOL WINAPI CertSetCertificateContextProperty(PCCERT_CONTEXT pCertContext, BOOL WINAPI CertSetCertificateContextProperty(PCCERT_CONTEXT pCertContext,
DWORD dwPropId, DWORD dwFlags, const void *pvData) DWORD dwPropId, DWORD dwFlags, const void *pvData)
{ {
PWINE_CERT_CONTEXT_REF ref = (PWINE_CERT_CONTEXT_REF)pCertContext;
BOOL ret; BOOL ret;
TRACE("(%p, %ld, %08lx, %p)\n", pCertContext, dwPropId, dwFlags, pvData); TRACE("(%p, %ld, %08lx, %p)\n", pCertContext, dwPropId, dwFlags, pvData);
...@@ -2148,8 +2077,8 @@ BOOL WINAPI CertSetCertificateContextProperty(PCCERT_CONTEXT pCertContext, ...@@ -2148,8 +2077,8 @@ BOOL WINAPI CertSetCertificateContextProperty(PCCERT_CONTEXT pCertContext,
SetLastError(HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER)); SetLastError(HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER));
return FALSE; return FALSE;
} }
ret = CRYPT_SetCertificateContextProperty(ref->context, dwPropId, ret = CRYPT_SetCertificateContextProperty((PWINE_CERT_CONTEXT)pCertContext,
dwFlags, pvData); dwPropId, dwFlags, pvData);
TRACE("returning %d\n", ret); TRACE("returning %d\n", ret);
return ret; return ret;
} }
...@@ -2157,7 +2086,7 @@ BOOL WINAPI CertSetCertificateContextProperty(PCCERT_CONTEXT pCertContext, ...@@ -2157,7 +2086,7 @@ BOOL WINAPI CertSetCertificateContextProperty(PCCERT_CONTEXT pCertContext,
PCCERT_CONTEXT WINAPI CertDuplicateCertificateContext( PCCERT_CONTEXT WINAPI CertDuplicateCertificateContext(
PCCERT_CONTEXT pCertContext) PCCERT_CONTEXT pCertContext)
{ {
PWINE_CERT_CONTEXT_REF context = (PWINE_CERT_CONTEXT_REF)pCertContext; PWINE_CERT_CONTEXT context = (PWINE_CERT_CONTEXT)pCertContext;
TRACE("(%p)\n", pCertContext); TRACE("(%p)\n", pCertContext);
InterlockedIncrement(&context->ref); InterlockedIncrement(&context->ref);
...@@ -2169,7 +2098,8 @@ BOOL WINAPI CertAddCertificateContextToStore(HCERTSTORE hCertStore, ...@@ -2169,7 +2098,8 @@ BOOL WINAPI CertAddCertificateContextToStore(HCERTSTORE hCertStore,
PCCERT_CONTEXT *ppStoreContext) PCCERT_CONTEXT *ppStoreContext)
{ {
PWINECRYPT_CERTSTORE store = (PWINECRYPT_CERTSTORE)hCertStore; PWINECRYPT_CERTSTORE store = (PWINECRYPT_CERTSTORE)hCertStore;
PWINE_CERT_CONTEXT_REF ref = (PWINE_CERT_CONTEXT_REF)pCertContext; PWINE_CERT_CONTEXT_DATA linked = CertContext_GetDataContext(
(PWINE_CERT_CONTEXT)pCertContext);
PWINE_CERT_CONTEXT cert; PWINE_CERT_CONTEXT cert;
BOOL ret; BOOL ret;
...@@ -2188,14 +2118,15 @@ BOOL WINAPI CertAddCertificateContextToStore(HCERTSTORE hCertStore, ...@@ -2188,14 +2118,15 @@ BOOL WINAPI CertAddCertificateContextToStore(HCERTSTORE hCertStore,
return FALSE; return FALSE;
} }
cert = CRYPT_CreateCertificateContext(ref->cert.dwCertEncodingType, cert = CRYPT_CreateCertificateContext(pCertContext->dwCertEncodingType,
ref->cert.pbCertEncoded, ref->cert.cbCertEncoded); pCertContext->pbCertEncoded, pCertContext->cbCertEncoded);
if (cert) if (cert)
{ {
ContextPropertyList_Copy(cert->properties, ref->context->properties); PWINE_CERT_CONTEXT_DATA certData = CertContext_GetDataContext(cert);
ContextPropertyList_Copy(certData->properties, linked->properties);
ret = store->addCert(store, cert, dwAddDisposition, ppStoreContext); ret = store->addCert(store, cert, dwAddDisposition, ppStoreContext);
if (!ret) CertFreeCertificateContext((PCCERT_CONTEXT)cert);
CRYPT_FreeCert(cert);
} }
else else
ret = FALSE; ret = FALSE;
...@@ -2224,8 +2155,7 @@ BOOL WINAPI CertAddEncodedCertificateToStore(HCERTSTORE hCertStore, ...@@ -2224,8 +2155,7 @@ BOOL WINAPI CertAddEncodedCertificateToStore(HCERTSTORE hCertStore,
if (cert) if (cert)
{ {
ret = hcs->addCert(hcs, cert, dwAddDisposition, ppCertContext); ret = hcs->addCert(hcs, cert, dwAddDisposition, ppCertContext);
if (!ret) CertFreeCertificateContext((PCCERT_CONTEXT)cert);
CRYPT_FreeCert(cert);
} }
else else
ret = FALSE; ret = FALSE;
...@@ -2237,7 +2167,6 @@ PCCERT_CONTEXT WINAPI CertEnumCertificatesInStore(HCERTSTORE hCertStore, ...@@ -2237,7 +2167,6 @@ PCCERT_CONTEXT WINAPI CertEnumCertificatesInStore(HCERTSTORE hCertStore,
PCCERT_CONTEXT pPrev) PCCERT_CONTEXT pPrev)
{ {
WINECRYPT_CERTSTORE *hcs = (WINECRYPT_CERTSTORE *)hCertStore; WINECRYPT_CERTSTORE *hcs = (WINECRYPT_CERTSTORE *)hCertStore;
PWINE_CERT_CONTEXT_REF prev = (PWINE_CERT_CONTEXT_REF)pPrev;
PCCERT_CONTEXT ret; PCCERT_CONTEXT ret;
TRACE("(%p, %p)\n", hCertStore, pPrev); TRACE("(%p, %p)\n", hCertStore, pPrev);
...@@ -2246,7 +2175,7 @@ PCCERT_CONTEXT WINAPI CertEnumCertificatesInStore(HCERTSTORE hCertStore, ...@@ -2246,7 +2175,7 @@ PCCERT_CONTEXT WINAPI CertEnumCertificatesInStore(HCERTSTORE hCertStore,
else if (hcs->dwMagic != WINE_CRYPTCERTSTORE_MAGIC) else if (hcs->dwMagic != WINE_CRYPTCERTSTORE_MAGIC)
ret = NULL; ret = NULL;
else else
ret = (PCCERT_CONTEXT)hcs->enumCert(hcs, prev); ret = (PCCERT_CONTEXT)hcs->enumCert(hcs, (PWINE_CERT_CONTEXT)pPrev);
return ret; return ret;
} }
...@@ -2451,25 +2380,39 @@ BOOL WINAPI CertSetCTLContextProperty(PCCTL_CONTEXT pCTLContext, ...@@ -2451,25 +2380,39 @@ BOOL WINAPI CertSetCTLContextProperty(PCCTL_CONTEXT pCTLContext,
return FALSE; return FALSE;
} }
static void CRYPT_UnrefCertificateContext(PWINE_CERT_CONTEXT_REF ref) static void CertDataContext_Free(PWINE_CERT_CONTEXT_DATA context)
{ {
if (InterlockedDecrement(&ref->ref) == 0) CryptMemFree(context->cert.pbCertEncoded);
{ LocalFree(context->cert.pCertInfo);
PWINECRYPT_CERTSTORE store = (PWINECRYPT_CERTSTORE)ref->cert.hCertStore; ContextPropertyList_Free(context->properties);
CryptMemFree(context);
}
static void CertLinkContext_Free(PWINE_CERT_CONTEXT_LINK context)
{
CertFreeCertificateContext((PCCERT_CONTEXT)context->linked);
CryptMemFree(context);
}
if (InterlockedDecrement(&ref->context->ref) == 0) static void CertContext_Release(PWINE_CERT_CONTEXT context)
{
if (InterlockedDecrement(&context->ref) == 0)
{
TRACE("freeing %p\n", context);
switch (context->type)
{ {
TRACE("%p's ref count is 0, freeing\n", ref->context); case ContextTypeData:
CRYPT_FreeCert(ref->context); CertDataContext_Free((PWINE_CERT_CONTEXT_DATA)context);
break;
case ContextTypeLink:
CertLinkContext_Free((PWINE_CERT_CONTEXT_LINK)context);
break;
default:
assert(0);
} }
else
TRACE("%p's ref count is %ld\n", ref->context, ref->context->ref);
if (store && store->dwMagic == WINE_CRYPTCERTSTORE_MAGIC &&
store->freeCert)
store->freeCert(ref);
TRACE("freeing %p\n", ref);
CryptMemFree(ref);
} }
else
TRACE("%p's ref count is %ld\n", context, context->ref);
} }
BOOL WINAPI CertFreeCertificateContext(PCCERT_CONTEXT pCertContext) BOOL WINAPI CertFreeCertificateContext(PCCERT_CONTEXT pCertContext)
...@@ -2477,7 +2420,7 @@ BOOL WINAPI CertFreeCertificateContext(PCCERT_CONTEXT pCertContext) ...@@ -2477,7 +2420,7 @@ BOOL WINAPI CertFreeCertificateContext(PCCERT_CONTEXT pCertContext)
TRACE("(%p)\n", pCertContext); TRACE("(%p)\n", pCertContext);
if (pCertContext) if (pCertContext)
CRYPT_UnrefCertificateContext((PWINE_CERT_CONTEXT_REF)pCertContext); CertContext_Release((PWINE_CERT_CONTEXT)pCertContext);
return TRUE; return TRUE;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment