Wine-0_9_1 vendor drop
Added: vendor/wine/dlls/crypt32/
Added: vendor/wine/dlls/crypt32/current/
Added: vendor/wine/dlls/crypt32/current/Makefile.in
Added: vendor/wine/dlls/crypt32/current/cert.c
Added: vendor/wine/dlls/crypt32/current/crypt32.spec
Added: vendor/wine/dlls/crypt32/current/crypt32_private.h
Added: vendor/wine/dlls/crypt32/current/encode.c
Added: vendor/wine/dlls/crypt32/current/main.c
Added: vendor/wine/dlls/crypt32/current/protectdata.c
_____
Added: vendor/wine/dlls/crypt32/current/Makefile.in
--- vendor/wine/dlls/crypt32/current/Makefile.in 2005-11-17
20:49:37 UTC (rev 19307)
+++ vendor/wine/dlls/crypt32/current/Makefile.in 2005-11-17
20:53:18 UTC (rev 19308)
@@ -0,0 +1,20 @@
+EXTRADEFS = -D_CRYPT32_
+TOPSRCDIR = @top_srcdir@
+TOPOBJDIR = ../..
+SRCDIR = @srcdir@
+VPATH = @srcdir@
+MODULE = crypt32.dll
+IMPORTLIB = libcrypt32.$(IMPLIBEXT)
+IMPORTS = user32 advapi32 kernel32 ntdll
+
+C_SRCS = \
+ cert.c \
+ encode.c \
+ protectdata.c \
+ main.c
+
+SUBDIRS = tests
+
+@MAKE_DLL_RULES@
+
+### Dependencies:
Property changes on: vendor/wine/dlls/crypt32/current/Makefile.in
___________________________________________________________________
Name: svn:keywords
+ Author Date Id Revision
Name: svn:eol-style
+ native
_____
Added: vendor/wine/dlls/crypt32/current/cert.c
--- vendor/wine/dlls/crypt32/current/cert.c 2005-11-17 20:49:37 UTC
(rev 19307)
+++ vendor/wine/dlls/crypt32/current/cert.c 2005-11-17 20:53:18 UTC
(rev 19308)
@@ -0,0 +1,3325 @@
+/*
+ * Copyright 2002 Mike McCormack for CodeWeavers
+ * Copyright 2004,2005 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307
USA
+ *
+ * FIXME:
+ * - As you can see in the stubs below, support for CRLs and CTLs is
missing.
+ * Mostly this should be copy-paste work, and some code (e.g.
extended
+ * properties) could be shared between them.
+ * - Opening a cert store provider should be morphed to support loading
+ * external DLLs.
+ * - The concept of physical stores and locations isn't implemented.
(This
+ * doesn't mean registry stores et al aren't implemented. See the
PSDK for
+ * registering and enumerating physical stores and locations.)
+ * - Many flags, options and whatnot are unimplemented.
+ */
+#include <assert.h>
+#include <stdarg.h>
+#include "windef.h"
+#include "winbase.h"
+#include "winnls.h"
+#include "winreg.h"
+#include "winuser.h"
+#include "wincrypt.h"
+#include "wine/debug.h"
+#include "wine/list.h"
+#include "excpt.h"
+#include "wine/exception.h"
+#include "crypt32_private.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(crypt);
+
+#define WINE_CRYPTCERTSTORE_MAGIC 0x74726563
+/* The following aren't defined in wincrypt.h, as they're "reserved"
*/
+#define CERT_CERT_PROP_ID 32
+#define CERT_CRL_PROP_ID 33
+#define CERT_CTL_PROP_ID 34
+
+/* Some typedefs that make it easier to abstract which type of context
we're
+ * working with.
+ */
+typedef const void *(WINAPI *CreateContextFunc)(DWORD
dwCertEncodingType,
+ const BYTE *pbCertEncoded, DWORD cbCertEncoded);
+typedef BOOL (WINAPI *AddContextToStoreFunc)(HCERTSTORE hCertStore,
+ const void *context, DWORD dwAddDisposition, const void
**ppStoreContext);
+typedef BOOL (WINAPI *AddEncodedContextToStoreFunc)(HCERTSTORE
hCertStore,
+ DWORD dwCertEncodingType, const BYTE *pbEncoded, DWORD cbEncoded,
+ DWORD dwAddDisposition, const void **ppContext);
+typedef const void *(WINAPI *EnumContextsInStoreFunc)(HCERTSTORE
hCertStore,
+ const void *pPrevContext);
+typedef BOOL (WINAPI *GetContextPropertyFunc)(const void *context,
+ DWORD dwPropID, void *pvData, DWORD *pcbData);
+typedef BOOL (WINAPI *SetContextPropertyFunc)(const void *context,
+ DWORD dwPropID, DWORD dwFlags, const void *pvData);
+typedef BOOL (WINAPI *SerializeElementFunc)(const void *context, DWORD
dwFlags,
+ BYTE *pbElement, DWORD *pcbElement);
+typedef BOOL (WINAPI *FreeContextFunc)(const void *context);
+typedef BOOL (WINAPI *DeleteContextFunc)(const void *context);
+
+/* An abstract context (certificate, CRL, or CTL) interface */
+typedef struct _WINE_CONTEXT_INTERFACE
+{
+ CreateContextFunc create;
+ AddContextToStoreFunc addContextToStore;
+ AddEncodedContextToStoreFunc addEncodedToStore;
+ EnumContextsInStoreFunc enumContextsInStore;
+ GetContextPropertyFunc getProp;
+ SetContextPropertyFunc setProp;
+ SerializeElementFunc serialize;
+ FreeContextFunc free;
+ DeleteContextFunc deleteFromStore;
+} WINE_CONTEXT_INTERFACE, *PWINE_CONTEXT_INTERFACE;
+
+static const WINE_CONTEXT_INTERFACE gCertInterface = {
+ (CreateContextFunc)CertCreateCertificateContext,
+ (AddContextToStoreFunc)CertAddCertificateContextToStore,
+ (AddEncodedContextToStoreFunc)CertAddEncodedCertificateToStore,
+ (EnumContextsInStoreFunc)CertEnumCertificatesInStore,
+ (GetContextPropertyFunc)CertGetCertificateContextProperty,
+ (SetContextPropertyFunc)CertSetCertificateContextProperty,
+ (SerializeElementFunc)CertSerializeCertificateStoreElement,
+ (FreeContextFunc)CertFreeCertificateContext,
+ (DeleteContextFunc)CertDeleteCertificateFromStore,
+};
+
+static const WINE_CONTEXT_INTERFACE gCRLInterface = {
+ (CreateContextFunc)CertCreateCRLContext,
+ (AddContextToStoreFunc)CertAddCRLContextToStore,
+ (AddEncodedContextToStoreFunc)CertAddEncodedCRLToStore,
+ (EnumContextsInStoreFunc)CertEnumCRLsInStore,
+ (GetContextPropertyFunc)CertGetCRLContextProperty,
+ (SetContextPropertyFunc)CertSetCRLContextProperty,
+ (SerializeElementFunc)CertSerializeCRLStoreElement,
+ (FreeContextFunc)CertFreeCRLContext,
+ (DeleteContextFunc)CertDeleteCRLFromStore,
+};
+
+static const WINE_CONTEXT_INTERFACE gCTLInterface = {
+ (CreateContextFunc)CertCreateCTLContext,
+ (AddContextToStoreFunc)CertAddCTLContextToStore,
+ (AddEncodedContextToStoreFunc)CertAddEncodedCTLToStore,
+ (EnumContextsInStoreFunc)CertEnumCTLsInStore,
+ (GetContextPropertyFunc)CertGetCTLContextProperty,
+ (SetContextPropertyFunc)CertSetCTLContextProperty,
+ (SerializeElementFunc)CertSerializeCTLStoreElement,
+ (FreeContextFunc)CertFreeCTLContext,
+ (DeleteContextFunc)CertDeleteCTLFromStore,
+};
+
+struct WINE_CRYPTCERTSTORE;
+
+typedef struct WINE_CRYPTCERTSTORE * (*StoreOpenFunc)(HCRYPTPROV
hCryptProv,
+ 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;
+
+/* Called to create a new reference to an existing cert context.
Should call
+ * CRYPT_InitCertRef to make sure the reference count is properly
updated.
+ * If the store does not provide any additional allocated data (that
is, does
+ * not need to implement a FreeCertFunc), it may use
CRYPT_CreateCertRef for
+ * this.
+ */
+typedef struct _WINE_CERT_CONTEXT_REF * (*CreateRefFunc)
+ (struct _WINE_CERT_CONTEXT *context, HCERTSTORE store);
+
+/* 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 {
+ StoreTypeMem,
+ StoreTypeCollection,
+ StoreTypeReg,
+ StoreTypeDummy,
+} CertStoreType;
+
+/* A cert store is polymorphic through the use of function pointers. A
type
+ * is still needed to distinguish collection stores from other types.
+ * On the function pointers:
+ * - closeStore is called when the store's ref count becomes 0
+ * - addCert is called with a PWINE_CERT_CONTEXT as the second
parameter
+ * - control is optional, but should be implemented by any store that
supports
+ * persistence
+ */
+typedef struct WINE_CRYPTCERTSTORE
+{
+ DWORD dwMagic;
+ LONG ref;
+ DWORD dwOpenFlags;
+ HCRYPTPROV cryptProv;
+ CertStoreType type;
+ PFN_CERT_STORE_PROV_CLOSE closeStore;
+ PFN_CERT_STORE_PROV_WRITE_CERT addCert;
+ CreateRefFunc createCertRef;
+ EnumCertFunc enumCert;
+ PFN_CERT_STORE_PROV_DELETE_CERT deleteCert;
+ FreeCertFunc freeCert; /* optional */
+ PFN_CERT_STORE_PROV_CONTROL control; /* optional */
+} WINECRYPT_CERTSTORE, *PWINECRYPT_CERTSTORE;
+
+/* A certificate context has pointers to data that are owned by this
module,
+ * so rather than duplicate the data every time a certificate context
is
+ * copied, I keep a reference count to the data. Thus I have two data
+ * structures, the "true" certificate context (that has the reference
count)
+ * 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
+ * with the reference version.
+ */
+typedef struct _WINE_CERT_CONTEXT
+{
+ CERT_CONTEXT cert;
+ LONG ref;
+ CRITICAL_SECTION cs;
+ struct list extendedProperties;
+} WINE_CERT_CONTEXT, *PWINE_CERT_CONTEXT;
+
+typedef struct _WINE_CERT_CONTEXT_REF
+{
+ CERT_CONTEXT cert;
+ WINE_CERT_CONTEXT *context;
+} WINE_CERT_CONTEXT_REF, *PWINE_CERT_CONTEXT_REF;
+
+/* An extended certificate property in serialized form is prefixed by
this
+ * header.
+ */
+typedef struct _WINE_CERT_PROP_HEADER
+{
+ DWORD propID;
+ DWORD unknown; /* always 1 */
+ DWORD cb;
+} WINE_CERT_PROP_HEADER, *PWINE_CERT_PROP_HEADER;
+
+/* Stores an extended property in a cert. */
+typedef struct _WINE_CERT_PROPERTY
+{
+ WINE_CERT_PROP_HEADER hdr;
+ LPBYTE pbData;
+ struct list entry;
+} WINE_CERT_PROPERTY, *PWINE_CERT_PROPERTY;
+
+/* A mem store has a list of these. They're also returned by the mem
store
+ * during enumeration.
+ */
+typedef struct _WINE_CERT_LIST_ENTRY
+{
+ WINE_CERT_CONTEXT_REF cert;
+ struct list entry;
+} WINE_CERT_LIST_ENTRY, *PWINE_CERT_LIST_ENTRY;
+
+typedef struct _WINE_MEMSTORE
+{
+ WINECRYPT_CERTSTORE hdr;
+ CRITICAL_SECTION cs;
+ struct list certs;
+} WINE_MEMSTORE, *PWINE_MEMSTORE;
+
+typedef struct _WINE_HASH_TO_DELETE
+{
+ BYTE hash[20];
+ struct list entry;
+} WINE_HASH_TO_DELETE, *PWINE_HASH_TO_DELETE;
+
+/* Returned by a reg store during enumeration. */
+typedef struct _WINE_REG_CERT_CONTEXT
+{
+ WINE_CERT_CONTEXT_REF cert;
+ PWINE_CERT_CONTEXT_REF childContext;
+} WINE_REG_CERT_CONTEXT, *PWINE_REG_CERT_CONTEXT;
+
+typedef struct _WINE_REGSTORE
+{
+ WINECRYPT_CERTSTORE hdr;
+ PWINECRYPT_CERTSTORE memStore;
+ HKEY key;
+ BOOL dirty;
+ CRITICAL_SECTION cs;
+ struct list certsToDelete;
+} WINE_REGSTORE, *PWINE_REGSTORE;
+
+typedef struct _WINE_STORE_LIST_ENTRY
+{
+ PWINECRYPT_CERTSTORE store;
+ DWORD dwUpdateFlags;
+ DWORD dwPriority;
+ struct list entry;
+} WINE_STORE_LIST_ENTRY, *PWINE_STORE_LIST_ENTRY;
+
+/* Returned by a collection store during enumeration.
+ * Note: relies on the list entry being valid after use, which a number
of
+ * conditions might make untrue (reentrancy, closing a collection store
before
+ * continuing an enumeration on it, ...). The tests seem to indicate
this
+ * sort of unsafety is okay, since Windows isn't well-behaved in these
+ * scenarios either.
+ */
+typedef struct _WINE_COLLECTION_CERT_CONTEXT
+{
+ WINE_CERT_CONTEXT_REF cert;
+ PWINE_STORE_LIST_ENTRY entry;
+ PWINE_CERT_CONTEXT_REF childContext;
+} WINE_COLLECTION_CERT_CONTEXT, *PWINE_COLLECTION_CERT_CONTEXT;
+
+typedef struct _WINE_COLLECTIONSTORE
+{
+ WINECRYPT_CERTSTORE hdr;
+ CRITICAL_SECTION cs;
+ struct list stores;
+} WINE_COLLECTIONSTORE, *PWINE_COLLECTIONSTORE;
+
+/* Like CertGetCertificateContextProperty, but operates directly on the
+ * WINE_CERT_CONTEXT. Doesn't support special-case properties, since
they
+ * are handled by CertGetCertificateContextProperty, and are particular
to the
+ * store in which the property exists (which is separate from the
context.)
+ */
+static BOOL WINAPI CRYPT_GetCertificateContextProperty(
+ PWINE_CERT_CONTEXT context, DWORD dwPropId, void *pvData, DWORD
*pcbData);
+
+/* Like CertSetCertificateContextProperty, but operates directly on the
+ * WINE_CERT_CONTEXT. Doesn't handle special cases, since they're
handled by
+ * CertSetCertificateContextProperty anyway.
+ */
+static BOOL WINAPI CRYPT_SetCertificateContextProperty(
+ PWINE_CERT_CONTEXT context, DWORD dwPropId, DWORD dwFlags, const void
*pvData);
+
+/* 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
+ * the serialized context (for example, bad hashes are retained.)
+ * *pdwContentType is set to the type of the returned context.
+ */
+static const void * WINAPI CRYPT_ReadSerializedElement(const BYTE
*pbElement,
+ DWORD cbElement, DWORD dwContextTypeFlags, DWORD *pdwContentType);
+
+/* filter for page-fault exceptions */
+static WINE_EXCEPTION_FILTER(page_fault)
+{
+ if (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION)
+ return EXCEPTION_EXECUTE_HANDLER;
+ return EXCEPTION_CONTINUE_SEARCH;
+}
+
+static void CRYPT_InitStore(WINECRYPT_CERTSTORE *store, HCRYPTPROV
hCryptProv,
+ DWORD dwFlags, CertStoreType type)
+{
+ store->ref = 1;
+ store->dwMagic = WINE_CRYPTCERTSTORE_MAGIC;
+ store->type = type;
+ if (!hCryptProv)
+ {
+ hCryptProv = CRYPT_GetDefaultProvider();
+ dwFlags |= CERT_STORE_NO_CRYPT_RELEASE_FLAG;
+ }
+ store->cryptProv = hCryptProv;
+ store->dwOpenFlags = dwFlags;
+}
+
+/* Initializes the reference ref to point to pCertContext, which is
assumed to
+ * be a PWINE_CERT_CONTEXT, and increments pCertContext's reference
count.
+ * Also sets the hCertStore member of the reference to store.
+ */
+static void CRYPT_InitCertRef(PWINE_CERT_CONTEXT_REF ref,
+ PWINE_CERT_CONTEXT context, HCERTSTORE store)
+{
+ TRACE("(%p, %p)\n", ref, context);
+ memcpy(&ref->cert, context, sizeof(ref->cert));
+ ref->context = context;
+ InterlockedIncrement(&context->ref);
+ 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));
+
+ if (pCertRef)
+ CRYPT_InitCertRef(pCertRef, context, store);
+ return pCertRef;
+}
+
+static BOOL WINAPI CRYPT_MemAddCert(HCERTSTORE store, PCCERT_CONTEXT
pCert,
+ DWORD dwAddDisposition)
+{
+ WINE_MEMSTORE *ms = (WINE_MEMSTORE *)store;
+ BOOL add = FALSE, ret;
+
+ TRACE("(%p, %p, %ld)\n", store, pCert, dwAddDisposition);
+
+ switch (dwAddDisposition)
+ {
+ case CERT_STORE_ADD_ALWAYS:
+ add = TRUE;
+ break;
+ case CERT_STORE_ADD_NEW:
+ {
+ BYTE hashToAdd[20], hash[20];
+ DWORD size = sizeof(hashToAdd);
+
+ ret =
CRYPT_GetCertificateContextProperty((PWINE_CERT_CONTEXT)pCert,
+ CERT_HASH_PROP_ID, hashToAdd, &size);
+ if (ret)
+ {
+ PWINE_CERT_LIST_ENTRY cursor;
+
+ /* Add if no cert with the same hash is found. */
+ add = TRUE;
+ EnterCriticalSection(&ms->cs);
+ LIST_FOR_EACH_ENTRY(cursor, &ms->certs,
WINE_CERT_LIST_ENTRY, entry)
+ {
+ size = sizeof(hash);
+ ret =
CertGetCertificateContextProperty(&cursor->cert.cert,
+ CERT_HASH_PROP_ID, hash, &size);
+ if (ret && !memcmp(hashToAdd, hash, size))
+ {
+ TRACE("found matching certificate, not adding\n");
+ SetLastError(CRYPT_E_EXISTS);
+ add = FALSE;
+ break;
+ }
+ }
+ LeaveCriticalSection(&ms->cs);
+ }
+ break;
+ }
+ case CERT_STORE_ADD_REPLACE_EXISTING:
+ {
+ BYTE hashToAdd[20], hash[20];
+ DWORD size = sizeof(hashToAdd);
+
+ add = TRUE;
+ ret =
CRYPT_GetCertificateContextProperty((PWINE_CERT_CONTEXT)pCert,
+ CERT_HASH_PROP_ID, hashToAdd, &size);
+ if (ret)
+ {
+ PWINE_CERT_LIST_ENTRY cursor, next;
+
+ /* Look for existing cert to delete */
+ EnterCriticalSection(&ms->cs);
+ LIST_FOR_EACH_ENTRY_SAFE(cursor, next, &ms->certs,
+ WINE_CERT_LIST_ENTRY, entry)
+ {
+ size = sizeof(hash);
+ ret =
CertGetCertificateContextProperty(&cursor->cert.cert,
+ CERT_HASH_PROP_ID, hash, &size);
+ if (ret && !memcmp(hashToAdd, hash, size))
+ {
+ TRACE("found matching certificate, replacing\n");
+ list_remove(&cursor->entry);
+ CertFreeCertificateContext((PCCERT_CONTEXT)cursor);
+ break;
+ }
+ }
+ LeaveCriticalSection(&ms->cs);
+ }
+ break;
+ }
+ default:
+ FIXME("Unimplemented add disposition %ld\n", dwAddDisposition);
+ add = FALSE;
+ }
+ if (add)
+ {
+ PWINE_CERT_LIST_ENTRY entry = CryptMemAlloc(
+ sizeof(WINE_CERT_LIST_ENTRY));
+
+ if (entry)
+ {
+ TRACE("adding %p\n", entry);
+ CRYPT_InitCertRef(&entry->cert, (PWINE_CERT_CONTEXT)pCert,
store);
+ list_init(&entry->entry);
+ EnterCriticalSection(&ms->cs);
+ list_add_tail(&ms->certs, &entry->entry);
+ LeaveCriticalSection(&ms->cs);
+ ret = TRUE;
+ }
+ else
+ ret = FALSE;
+ }
+ else
+ ret = FALSE;
+ return ret;
+}
+
+static PWINE_CERT_CONTEXT_REF CRYPT_MemEnumCert(PWINECRYPT_CERTSTORE
store,
+ PWINE_CERT_CONTEXT_REF pPrev)
+{
+ WINE_MEMSTORE *ms = (WINE_MEMSTORE *)store;
+ PWINE_CERT_LIST_ENTRY prevEntry = (PWINE_CERT_LIST_ENTRY)pPrev,
ret;
+ struct list *listNext;
+
+ TRACE("(%p, %p)\n", store, pPrev);
+ EnterCriticalSection(&ms->cs);
+ if (prevEntry)
+ {
+ listNext = list_next(&ms->certs, &prevEntry->entry);
+ CertFreeCertificateContext((PCCERT_CONTEXT)pPrev);
+ }
+ else
+ listNext = list_next(&ms->certs, &ms->certs);
+ if (listNext)
+ {
+ ret = CryptMemAlloc(sizeof(WINE_CERT_LIST_ENTRY));
+ memcpy(ret, LIST_ENTRY(listNext, WINE_CERT_LIST_ENTRY, entry),
+ sizeof(WINE_CERT_LIST_ENTRY));
+ InterlockedIncrement(&ret->cert.context->ref);
+ }
+ else
+ {
+ SetLastError(CRYPT_E_NOT_FOUND);
+ ret = NULL;
+ }
+ LeaveCriticalSection(&ms->cs);
+
+ TRACE("returning %p\n", ret);
+ return (PWINE_CERT_CONTEXT_REF)ret;
+}
+
+static BOOL WINAPI CRYPT_MemDeleteCert(HCERTSTORE hCertStore,
+ PCCERT_CONTEXT pCertContext, DWORD dwFlags)
+{
+ WINE_MEMSTORE *store = (WINE_MEMSTORE *)hCertStore;
+ WINE_CERT_CONTEXT_REF *ref = (WINE_CERT_CONTEXT_REF *)pCertContext;
+ PWINE_CERT_LIST_ENTRY cert, next;
+ BOOL ret;
+
+ /* Find the entry associated with the passed-in context, since the
+ * 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);
+ LIST_FOR_EACH_ENTRY_SAFE(cert, next, &store->certs,
WINE_CERT_LIST_ENTRY,
+ entry)
+ {
+ 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;
+ break;
+ }
+ }
+ ret = TRUE;
+ LeaveCriticalSection(&store->cs);
+ return ret;
+}
+
+static void WINAPI CRYPT_MemCloseStore(HCERTSTORE hCertStore, DWORD
dwFlags)
+{
+ WINE_MEMSTORE *store = (WINE_MEMSTORE *)hCertStore;
+ PWINE_CERT_LIST_ENTRY cert, next;
+
+ TRACE("(%p, %08lx)\n", store, dwFlags);
+ if (dwFlags)
+ FIXME("Unimplemented flags: %08lx\n", dwFlags);
+
+ /* Note that CertFreeCertificateContext calls HeapFree 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,
+ entry)
+ {
+ TRACE("removing %p\n", cert);
+ list_remove(&cert->entry);
+ CertFreeCertificateContext((PCCERT_CONTEXT)cert);
+ }
+ DeleteCriticalSection(&store->cs);
+ CryptMemFree(store);
+}
+
+static WINECRYPT_CERTSTORE *CRYPT_MemOpenStore(HCRYPTPROV hCryptProv,
+ DWORD dwFlags, const void *pvPara)
+{
+ PWINE_MEMSTORE store;
+
+ TRACE("(%ld, %08lx, %p)\n", hCryptProv, dwFlags, pvPara);
+
+ if (dwFlags & CERT_STORE_DELETE_FLAG)
+ {
+ SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+ store = NULL;
+ }
+ else
+ {
+ store = CryptMemAlloc(sizeof(WINE_MEMSTORE));
+ if (store)
+ {
+ memset(store, 0, sizeof(WINE_MEMSTORE));
+ CRYPT_InitStore(&store->hdr, hCryptProv, dwFlags,
StoreTypeMem);
+ store->hdr.closeStore = CRYPT_MemCloseStore;
+ store->hdr.addCert = CRYPT_MemAddCert;
+ store->hdr.createCertRef = CRYPT_CreateCertRef;
+ store->hdr.enumCert = CRYPT_MemEnumCert;
+ store->hdr.deleteCert = CRYPT_MemDeleteCert;
+ store->hdr.freeCert = NULL;
+ InitializeCriticalSection(&store->cs);
+ list_init(&store->certs);
+ }
+ }
+ return (PWINECRYPT_CERTSTORE)store;
+}
+
+static BOOL WINAPI CRYPT_CollectionAddCert(HCERTSTORE store,
+ PCCERT_CONTEXT pCert, DWORD dwAddDisposition)
+{
+ PWINE_COLLECTIONSTORE cs = (PWINE_COLLECTIONSTORE)store;
+ PWINE_STORE_LIST_ENTRY entry, next;
+ BOOL ret;
+
+ TRACE("(%p, %p, %ld)\n", store, pCert, dwAddDisposition);
+
+ ret = FALSE;
+ EnterCriticalSection(&cs->cs);
+ LIST_FOR_EACH_ENTRY_SAFE(entry, next, &cs->stores,
WINE_STORE_LIST_ENTRY,
+ entry)
+ {
+ if (entry->dwUpdateFlags & CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG)
+ {
+ ret = entry->store->addCert(entry->store, pCert,
dwAddDisposition);
+ break;
+ }
+ }
+ LeaveCriticalSection(&cs->cs);
+ SetLastError(ret ? ERROR_SUCCESS :
HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED));
+ 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->entry = NULL;
+ ret->childContext = NULL;
+ }
+ return (PWINE_CERT_CONTEXT_REF)ret;
+}
+
+static void WINAPI CRYPT_CollectionCloseStore(HCERTSTORE store, DWORD
dwFlags)
+{
+ PWINE_COLLECTIONSTORE cs = (PWINE_COLLECTIONSTORE)store;
+ PWINE_STORE_LIST_ENTRY entry, next;
+
+ TRACE("(%p, %08lx)\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);
+ }
+ DeleteCriticalSection(&cs->cs);
+ CryptMemFree(cs);
+}
+
+/* Advances a collection enumeration by one cert, if possible, where
advancing
+ * means:
+ * - calling the current store's enumeration function once, and
returning
+ * the enumerated cert 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 PWINE_COLLECTION_CERT_CONTEXT CRYPT_CollectionAdvanceEnum(
+ PWINE_COLLECTIONSTORE store, PWINE_STORE_LIST_ENTRY storeEntry,
+ PWINE_COLLECTION_CERT_CONTEXT pPrev)
+{
+ PWINE_COLLECTION_CERT_CONTEXT ret;
+ PWINE_CERT_CONTEXT_REF child;
+
+ TRACE("(%p, %p, %p)\n", store, storeEntry, pPrev);
+
+ if (pPrev)
+ {
+ child =
storeEntry->store->enumCert((HCERTSTORE)storeEntry->store,
+ pPrev->childContext);
+ if (child)
+ {
+ ret = pPrev;
+ memcpy(&ret->cert, child, sizeof(WINE_CERT_CONTEXT_REF));
+ ret->cert.cert.hCertStore = (HCERTSTORE)store;
+ InterlockedIncrement(&ret->cert.context->ref);
+ ret->childContext = child;
+ }
+ else
+ {
+ struct list *storeNext = list_next(&store->stores,
+ &storeEntry->entry);
+
+ pPrev->childContext = NULL;
+ CertFreeCertificateContext((PCCERT_CONTEXT)pPrev);
+ if (storeNext)
+ {
+ storeEntry = LIST_ENTRY(storeNext,
WINE_STORE_LIST_ENTRY,
+ entry);
+ ret = CRYPT_CollectionAdvanceEnum(store, storeEntry,
NULL);
+ }
+ else
+ {
+ SetLastError(CRYPT_E_NOT_FOUND);
+ ret = NULL;
+ }
+ }
+ }
+ else
+ {
+ child =
storeEntry->store->enumCert((HCERTSTORE)storeEntry->store,
+ NULL);
+ if (child)
+ {
+ ret =
(PWINE_COLLECTION_CERT_CONTEXT)CRYPT_CollectionCreateCertRef(
+ child->context, store);
+ if (ret)
+ {
+ ret->entry = storeEntry;
+ ret->childContext = child;
+ }
+ else
+ CertFreeCertificateContext((PCCERT_CONTEXT)child);
+ }
+ else
+ {
+ struct list *storeNext = list_next(&store->stores,
+ &storeEntry->entry);
+
+ if (storeNext)
+ {
+ storeEntry = LIST_ENTRY(storeNext,
WINE_STORE_LIST_ENTRY,
+ entry);
+ ret = CRYPT_CollectionAdvanceEnum(store, storeEntry,
NULL);
+ }
+ else
+ {
+ SetLastError(CRYPT_E_NOT_FOUND);
+ ret = NULL;
+ }
+ }
+ }
+ TRACE("returning %p\n", ret);
+ return ret;
+}
+
+static PWINE_CERT_CONTEXT_REF CRYPT_CollectionEnumCert(
+ PWINECRYPT_CERTSTORE store, PWINE_CERT_CONTEXT_REF pPrev)
+{
+ PWINE_COLLECTIONSTORE cs = (PWINE_COLLECTIONSTORE)store;
+ PWINE_COLLECTION_CERT_CONTEXT prevEntry =
+ (PWINE_COLLECTION_CERT_CONTEXT)pPrev, ret;
+
+ TRACE("(%p, %p)\n", store, pPrev);
+
+ if (prevEntry)
+ {
+ EnterCriticalSection(&cs->cs);
+ ret = CRYPT_CollectionAdvanceEnum(cs, prevEntry->entry,
prevEntry);
+ LeaveCriticalSection(&cs->cs);
+ }
+ else
+ {
+ EnterCriticalSection(&cs->cs);
+ if (!list_empty(&cs->stores))
+ {
+ PWINE_STORE_LIST_ENTRY storeEntry;
+
+ storeEntry = LIST_ENTRY(cs->stores.next,
WINE_STORE_LIST_ENTRY,
+ entry);
+ ret = CRYPT_CollectionAdvanceEnum(cs, storeEntry,
prevEntry);
+ }
+ else
+ {
+ SetLastError(CRYPT_E_NOT_FOUND);
+ ret = NULL;
+ }
+ LeaveCriticalSection(&cs->cs);
+ }
+ TRACE("returning %p\n", ret);
+ return (PWINE_CERT_CONTEXT_REF)ret;
+}
+
+static BOOL WINAPI CRYPT_CollectionDeleteCert(HCERTSTORE hCertStore,
+ PCCERT_CONTEXT pCertContext, DWORD dwFlags)
+{
+ PWINE_COLLECTION_CERT_CONTEXT context =
+ (PWINE_COLLECTION_CERT_CONTEXT)pCertContext;
+ BOOL ret;
+
+ TRACE("(%p, %p, %08lx)\n", hCertStore, pCertContext, dwFlags);
+
+ ret =
CertDeleteCertificateFromStore((PCCERT_CONTEXT)context->childContext);
+ if (ret)
+ context->childContext = NULL;
+ 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,
+ 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.addCert = CRYPT_CollectionAddCert;
+ store->hdr.createCertRef = CRYPT_CollectionCreateCertRef;
+ store->hdr.enumCert = CRYPT_CollectionEnumCert;
+ store->hdr.deleteCert = CRYPT_CollectionDeleteCert;
+ store->hdr.freeCert = CRYPT_CollectionFreeCert;
+ InitializeCriticalSection(&store->cs);
+ list_init(&store->stores);
+ }
+ }
+ return (PWINECRYPT_CERTSTORE)store;
+}
+
+static void CRYPT_HashToStr(LPBYTE hash, LPWSTR asciiHash)
+{
+ static const WCHAR fmt[] = { '%','0','2','X',0 };
+ DWORD i;
+
+ assert(hash);
+ assert(asciiHash);
+
+ for (i = 0; i < 20; i++)
+ wsprintfW(asciiHash + i * 2, fmt, hash[i]);
+}
+
+static const WCHAR CertsW[] = {
'C','e','r','t','i','f','i','c','a','t','e','s',
+ 0 };
+static const WCHAR CRLsW[] = { 'C','R','L','s',0 };
+static const WCHAR CTLsW[] = { 'C','T','L','s',0 };
+static const WCHAR BlobW[] = { 'B','l','o','b',0 };
+
+static void CRYPT_RegReadSerializedFromReg(PWINE_REGSTORE store, HKEY
key,
+ DWORD contextType)
+{
+ LONG rc;
+ DWORD index = 0;
+ WCHAR subKeyName[MAX_PATH];
+
+ do {
+ DWORD size = sizeof(subKeyName) / sizeof(WCHAR);
+
+ rc = RegEnumKeyExW(key, index++, subKeyName, &size, NULL, NULL,
NULL,
+ NULL);
+ if (!rc)
+ {
+ HKEY subKey;
+
+ rc = RegOpenKeyExW(key, subKeyName, 0, KEY_READ, &subKey);
+ if (!rc)
+ {
+ LPBYTE buf = NULL;
+
+ size = 0;
+ rc = RegQueryValueExW(subKey, BlobW, NULL, NULL, NULL,
&size);
+ if (!rc)
+ buf = CryptMemAlloc(size);
+ if (buf)
+ {
+ rc = RegQueryValueExW(subKey, BlobW, NULL, NULL,
buf,
+ &size);
+ if (!rc)
+ {
+ const void *context;
+ DWORD addedType;
+
+ TRACE("Adding cert with hash %s\n",
+ debugstr_w(subKeyName));
+ context = CRYPT_ReadSerializedElement(buf,
size,
+ contextType, &addedType);
+ if (context)
+ {
+ const WINE_CONTEXT_INTERFACE
*contextInterface;
+ BYTE hash[20];
+
+ switch (addedType)
+ {
+ case CERT_STORE_CERTIFICATE_CONTEXT:
+ contextInterface = &gCertInterface;
+ break;
+ case CERT_STORE_CRL_CONTEXT:
+ contextInterface = &gCRLInterface;
+ break;
+ case CERT_STORE_CTL_CONTEXT:
+ contextInterface = &gCTLInterface;
+ break;
+ default:
+ contextInterface = NULL;
+ }
+ if (contextInterface)
+ {
+ size = sizeof(hash);
+ if (contextInterface->getProp(context,
+ CERT_HASH_PROP_ID, hash, &size))
+ {
+ WCHAR asciiHash[20 * 2 + 1];
+
+ CRYPT_HashToStr(hash, asciiHash);
+ TRACE("comparing %s\n",
+ debugstr_w(asciiHash));
+ TRACE("with %s\n",
debugstr_w(subKeyName));
+ if (!lstrcmpW(asciiHash,
subKeyName))
+ {
+ TRACE("hash matches,
adding\n");
+
contextInterface->addContextToStore(
+ store, context,
+
CERT_STORE_ADD_REPLACE_EXISTING, NULL);
+ }
+ else
+ {
+ TRACE("hash doesn't match,
ignoring\n");
+
contextInterface->free(context);
+ }
+ }
+ }
+ }
+ }
+ CryptMemFree(buf);
+ }
+ RegCloseKey(subKey);
+ }
+ /* Ignore intermediate errors, continue enumerating */
+ rc = ERROR_SUCCESS;
+ }
+ } while (!rc);
+}
+
+static void CRYPT_RegReadFromReg(PWINE_REGSTORE store)
+{
+ static const WCHAR *subKeys[] = { CertsW, CRLsW, CTLsW };
+ static const DWORD contextFlags[] = {
CERT_STORE_CERTIFICATE_CONTEXT_FLAG,
+ CERT_STORE_CRL_CONTEXT_FLAG, CERT_STORE_CTL_CONTEXT_FLAG };
+ DWORD i;
+
+ for (i = 0; i < sizeof(subKeys) / sizeof(subKeys[0]); i++)
+ {
+ HKEY key;
+ LONG rc;
+
+ rc = RegCreateKeyExW(store->key, subKeys[i], 0, NULL, 0,
KEY_READ, NULL,
+ &key, NULL);
+ if (!rc)
+ {
+ CRYPT_RegReadSerializedFromReg(store, key,
contextFlags[i]);
+ RegCloseKey(key);
+ }
+ }
+}
[truncated at 1000 lines; 9831 more skipped]