/*
- * Copyright 2002
- Mike McCormack for CodeWeavers
+ * Copyright 2002 Mike McCormack for CodeWeavers
* Copyright 2004,2005 Juan Lang
*
* This library is free software; you can redistribute it and/or
* registering and enumerating physical stores and locations.)
* - Many flags, options and whatnot are unimplemented.
*/
-
-#include "precomp.h"
+#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);
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)
{
memcpy(&ref->cert, context, sizeof(ref->cert));
ref->context = context;
InterlockedIncrement(&context->ref);
+ TRACE("%p's ref count is %ld\n", context, context->ref);
ref->cert.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;
}
else
ret = FALSE;
+ TRACE("returning %d\n", ret);
return ret;
}
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);
+ if (ret)
+ {
+ memcpy(ret, LIST_ENTRY(listNext, WINE_CERT_LIST_ENTRY, entry),
+ sizeof(WINE_CERT_LIST_ENTRY));
+ InterlockedIncrement(&ret->cert.context->ref);
+ }
}
else
{
return (PWINE_CERT_CONTEXT_REF)ret;
}
+static void CRYPT_UnrefCertificateContext(PWINE_CERT_CONTEXT_REF ref);
+
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;
+ BOOL ret = TRUE;
/* 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
* protected.
*/
list_remove(&cert->entry);
+ /* FIXME: generally I should do the following, otherwise there is
+ * a memory leak. But doing so when called by
+ * CertDeleteCertificateFromStore results in a double free, so
+ * leaving commented for now.
+ ret = CertFreeCertificateContext((PCCERT_CONTEXT)cert);
+ */
cert->entry.prev = cert->entry.next = &store->certs;
break;
}
}
- ret = TRUE;
LeaveCriticalSection(&store->cs);
return ret;
}
{
PWINE_COLLECTION_CERT_CONTEXT ret;
PWINE_CERT_CONTEXT_REF child;
+ struct list *storeNext = list_next(&store->stores, &storeEntry->entry);
TRACE("(%p, %p, %p)\n", store, storeEntry, pPrev);
+ child = storeEntry->store->enumCert((HCERTSTORE)storeEntry->store,
+ pPrev ? pPrev->childContext : NULL);
if (pPrev)
{
- child = storeEntry->store->enumCert((HCERTSTORE)storeEntry->store,
- pPrev->childContext);
- if (child)
+ pPrev->childContext = NULL;
+ CertFreeCertificateContext((PCCERT_CONTEXT)pPrev);
+ pPrev = NULL;
+ }
+ if (child)
+ {
+ ret = (PWINE_COLLECTION_CERT_CONTEXT)CRYPT_CollectionCreateCertRef(
+ child->context, store);
+ if (ret)
{
- ret = pPrev;
- memcpy(&ret->cert, child, sizeof(WINE_CERT_CONTEXT_REF));
- ret->cert.cert.hCertStore = (HCERTSTORE)store;
- InterlockedIncrement(&ret->cert.context->ref);
+ ret->entry = storeEntry;
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;
- }
- }
+ CertFreeCertificateContext((PCCERT_CONTEXT)child);
}
else
{
- child = storeEntry->store->enumCert((HCERTSTORE)storeEntry->store,
- NULL);
- if (child)
+ if (storeNext)
{
- ret = (PWINE_COLLECTION_CERT_CONTEXT)CRYPT_CollectionCreateCertRef(
- child->context, store);
- if (ret)
- {
- ret->entry = storeEntry;
- ret->childContext = child;
- }
- else
- CertFreeCertificateContext((PCCERT_CONTEXT)child);
+ storeEntry = LIST_ENTRY(storeNext, WINE_STORE_LIST_ENTRY, entry);
+ ret = CRYPT_CollectionAdvanceEnum(store, storeEntry, NULL);
}
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;
- }
+ SetLastError(CRYPT_E_NOT_FOUND);
+ ret = NULL;
}
}
TRACE("returning %p\n", ret);
CERT_STORE_ADD_REPLACE_EXISTING, NULL);
}
else
- {
TRACE("hash doesn't match, ignoring\n");
- contextInterface->free(context);
- }
}
+ contextInterface->free(context);
}
}
}
static PWINE_CERT_CONTEXT_REF CRYPT_RegCreateCertRef(
PWINE_CERT_CONTEXT context, HCERTSTORE store)
{
- PWINE_REG_CERT_CONTEXT ret = CryptMemAlloc(
- sizeof(WINE_REG_CERT_CONTEXT));
+ PWINE_REG_CERT_CONTEXT ret = CryptMemAlloc(sizeof(WINE_REG_CERT_CONTEXT));
if (ret)
{
TRACE("(%p, %p)\n", store, pPrev);
- if (pPrev)
+ child = rs->memStore->enumCert(rs->memStore, prev ? prev->childContext
+ : NULL);
+ if (prev)
{
- child = rs->memStore->enumCert(rs->memStore, prev->childContext);
- if (child)
- {
- ret = (PWINE_REG_CERT_CONTEXT)pPrev;
- memcpy(&ret->cert, child, sizeof(WINE_CERT_CONTEXT_REF));
- ret->cert.cert.hCertStore = (HCERTSTORE)store;
- ret->childContext = child;
- }
+ prev->childContext = NULL;
+ CertFreeCertificateContext((PCCERT_CONTEXT)prev);
+ prev = NULL;
}
- else
+ if (child)
{
- child = rs->memStore->enumCert(rs->memStore, NULL);
- if (child)
- {
- ret = CryptMemAlloc(sizeof(WINE_REG_CERT_CONTEXT));
-
- if (ret)
- {
- memcpy(&ret->cert, child, sizeof(WINE_CERT_CONTEXT_REF));
- ret->cert.cert.hCertStore = (HCERTSTORE)store;
- ret->childContext = child;
- }
- else
- CertFreeCertificateContext((PCCERT_CONTEXT)child);
- }
+ ret = (PWINE_REG_CERT_CONTEXT)CRYPT_RegCreateCertRef(child->context,
+ store);
+ if (ret)
+ ret->childContext = child;
+ else
+ CertFreeCertificateContext((PCCERT_CONTEXT)child);
}
return (PWINE_CERT_CONTEXT_REF)ret;
}
return ret;
}
+static BOOL CRYPT_GetCertHashProp(PWINE_CERT_CONTEXT context, DWORD dwPropId,
+ ALG_ID algID, const BYTE *toHash, DWORD toHashLen, void *pvData,
+ DWORD *pcbData)
+{
+ BOOL ret = CryptHashCertificate(0, algID, 0, toHash, toHashLen, pvData,
+ pcbData);
+ if (ret)
+ {
+ CRYPT_DATA_BLOB blob = { *pcbData, pvData };
+
+ ret = CRYPT_SetCertificateContextProperty(context, dwPropId,
+ 0, &blob);
+ }
+ return ret;
+}
+
static BOOL WINAPI CRYPT_GetCertificateContextProperty(
PWINE_CERT_CONTEXT context, DWORD dwPropId, void *pvData, DWORD *pcbData)
{
switch (dwPropId)
{
case CERT_SHA1_HASH_PROP_ID:
- ret = CryptHashCertificate(0, CALG_SHA1, 0,
+ ret = CRYPT_GetCertHashProp(context, dwPropId, CALG_SHA1,
context->cert.pbCertEncoded, context->cert.cbCertEncoded, pvData,
pcbData);
- if (ret)
- {
- CRYPT_DATA_BLOB blob = { *pcbData, pvData };
-
- ret = CRYPT_SetCertificateContextProperty(context, dwPropId,
- 0, &blob);
- }
break;
- case CERT_KEY_PROV_INFO_PROP_ID:
case CERT_MD5_HASH_PROP_ID:
- case CERT_SIGNATURE_HASH_PROP_ID:
- case CERT_KEY_IDENTIFIER_PROP_ID:
+ ret = CRYPT_GetCertHashProp(context, dwPropId, CALG_MD5,
+ context->cert.pbCertEncoded, context->cert.cbCertEncoded, pvData,
+ pcbData);
+ break;
+ case CERT_SUBJECT_NAME_MD5_HASH_PROP_ID:
+ ret = CRYPT_GetCertHashProp(context, dwPropId, CALG_MD5,
+ context->cert.pCertInfo->Subject.pbData,
+ context->cert.pCertInfo->Subject.cbData,
+ pvData, pcbData);
+ break;
case CERT_SUBJECT_PUBLIC_KEY_MD5_HASH_PROP_ID:
+ ret = CRYPT_GetCertHashProp(context, dwPropId, CALG_MD5,
+ context->cert.pCertInfo->SubjectPublicKeyInfo.PublicKey.pbData,
+ context->cert.pCertInfo->SubjectPublicKeyInfo.PublicKey.cbData,
+ pvData, pcbData);
+ break;
+ case CERT_SIGNATURE_HASH_PROP_ID:
case CERT_ISSUER_SERIAL_NUMBER_MD5_HASH_PROP_ID:
- case CERT_SUBJECT_NAME_MD5_HASH_PROP_ID:
FIXME("implicit property %ld\n", dwPropId);
+ SetLastError(CRYPT_E_NOT_FOUND);
break;
+ default:
+ SetLastError(CRYPT_E_NOT_FOUND);
}
}
LeaveCriticalSection(&context->cs);
case CERT_PVK_FILE_PROP_ID:
case CERT_SIGNATURE_HASH_PROP_ID:
case CERT_ISSUER_PUBLIC_KEY_MD5_HASH_PROP_ID:
+ case CERT_SUBJECT_NAME_MD5_HASH_PROP_ID:
case CERT_SUBJECT_PUBLIC_KEY_MD5_HASH_PROP_ID:
case CERT_ENROLLMENT_PROP_ID:
case CERT_CROSS_CERT_DIST_POINTS_PROP_ID:
else
{
ret = hcs->deleteCert(hcs, pCertContext, 0);
- CertFreeCertificateContext(pCertContext);
+ if (ret)
+ CertFreeCertificateContext(pCertContext);
}
}
return ret;
}
}
}
- _SEH_EXCEPT(page_fault)
+ __EXCEPT_PAGE_FAULT
{
SetLastError(STATUS_ACCESS_VIOLATION);
context = NULL;
return ret;
}
+static void CRYPT_UnrefCertificateContext(PWINE_CERT_CONTEXT_REF ref)
+{
+ if (InterlockedDecrement(&ref->context->ref) == 0)
+ {
+ TRACE("%p's ref count is 0, freeing\n", ref->context);
+ CRYPT_FreeCert(ref->context);
+ }
+ else
+ TRACE("%p's ref count is %ld\n", ref->context, ref->context->ref);
+}
+
BOOL WINAPI CertFreeCertificateContext(PCCERT_CONTEXT pCertContext)
{
TRACE("(%p)\n", pCertContext);
PWINE_CERT_CONTEXT_REF ref = (PWINE_CERT_CONTEXT_REF)pCertContext;
PWINECRYPT_CERTSTORE store = (PWINECRYPT_CERTSTORE)ref->cert.hCertStore;
- if (InterlockedDecrement(&ref->context->ref) == 0)
- {
- TRACE("%p's ref count is 0, freeing\n", ref->context);
- CRYPT_FreeCert(ref->context);
- }
- else
- TRACE("%p's ref count is %ld\n", ref->context, ref->context->ref);
+ CRYPT_UnrefCertificateContext(ref);
if (store && store->dwMagic == WINE_CRYPTCERTSTORE_MAGIC &&
store->freeCert)
store->freeCert(ref);
+ TRACE("freeing %p\n", ref);
CryptMemFree(ref);
}
return TRUE;
return ret;
}
-HCRYPTOIDFUNCSET WINAPI CryptInitOIDFunctionSet(LPCSTR pszFuncName, DWORD dwFlags)
-{
- FIXME("stub: %s %lx\n", debugstr_a(pszFuncName), dwFlags);
- return NULL;
-}
-
-BOOL WINAPI CryptUnregisterDefaultOIDFunction(DWORD dwEncodingType,
- LPCSTR pszFuncName, LPCWSTR pwszDll)
+BOOL WINAPI CryptVerifyMessageSignature(/*PCRYPT_VERIFY_MESSAGE_PARA*/ void* pVerifyPara,
+ DWORD dwSignerIndex, const BYTE* pbSignedBlob, DWORD cbSignedBlob,
+ BYTE* pbDecoded, DWORD* pcbDecoded, PCCERT_CONTEXT* ppSignerCert)
{
- FIXME("stub: %lx %s %s\n", dwEncodingType, debugstr_a(pszFuncName), debugstr_w(pwszDll));
+ FIXME("stub: %p, %ld, %p, %ld, %p, %p, %p\n",
+ pVerifyPara, dwSignerIndex, pbSignedBlob, cbSignedBlob,
+ pbDecoded, pcbDecoded, ppSignerCert);
return FALSE;
}