[CRYPT32]
authorAmine Khaldi <amine.khaldi@reactos.org>
Tue, 22 Apr 2014 15:10:43 +0000 (15:10 +0000)
committerAmine Khaldi <amine.khaldi@reactos.org>
Tue, 22 Apr 2014 15:10:43 +0000 (15:10 +0000)
* Sync with Wine 1.7.17.
CORE-8080

svn path=/trunk/; revision=62883

22 files changed:
reactos/dll/win32/crypt32/CMakeLists.txt
reactos/dll/win32/crypt32/cert.c
reactos/dll/win32/crypt32/chain.c
reactos/dll/win32/crypt32/collectionstore.c
reactos/dll/win32/crypt32/context.c
reactos/dll/win32/crypt32/crl.c
reactos/dll/win32/crypt32/crypt32_private.h
reactos/dll/win32/crypt32/ctl.c
reactos/dll/win32/crypt32/encode.c
reactos/dll/win32/crypt32/filestore.c
reactos/dll/win32/crypt32/main.c
reactos/dll/win32/crypt32/msg.c
reactos/dll/win32/crypt32/object.c
reactos/dll/win32/crypt32/oid.c
reactos/dll/win32/crypt32/proplist.c
reactos/dll/win32/crypt32/provstore.c
reactos/dll/win32/crypt32/regstore.c
reactos/dll/win32/crypt32/rootstore.c
reactos/dll/win32/crypt32/serialize.c
reactos/dll/win32/crypt32/store.c
reactos/dll/win32/crypt32/str.c
reactos/media/doc/README.WINE

index aef59eb..a4eedfa 100644 (file)
@@ -46,5 +46,6 @@ add_library(crypt32 SHARED
 set_module_type(crypt32 win32dll)
 target_link_libraries(crypt32 wine ${PSEH_LIB} oldnames)
 add_importlibs(crypt32 user32 advapi32 msvcrt kernel32 ntdll)
+add_delay_importlibs(crypt32 cryptnet)
 add_pch(crypt32 crypt32_private.h SOURCE)
 add_cd_file(TARGET crypt32 DESTINATION reactos/system32 FOR all)
index 052a024..c1728d5 100644 (file)
@@ -29,7 +29,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(crypt);
  * CertGetCertificateContextProperty, and are particular to the store in which
  * the property exists (which is separate from the context.)
  */
-static BOOL CertContext_GetProperty(void *context, DWORD dwPropId,
+static BOOL CertContext_GetProperty(cert_t *cert, DWORD dwPropId,
  void *pvData, DWORD *pcbData);
 
 /* Internal version of CertSetCertificateContextProperty that sets properties
@@ -37,7 +37,7 @@ static BOOL CertContext_GetProperty(void *context, DWORD dwPropId,
  * type.) Doesn't handle special cases, since they're handled by
  * CertSetCertificateContextProperty anyway.
  */
-static BOOL CertContext_SetProperty(void *context, DWORD dwPropId,
+static BOOL CertContext_SetProperty(cert_t *cert, DWORD dwPropId,
  DWORD dwFlags, const void *pvData);
 
 BOOL WINAPI CertAddEncodedCertificateToStore(HCERTSTORE hCertStore,
@@ -100,12 +100,190 @@ BOOL WINAPI CertAddEncodedCertificateToSystemStoreW(LPCWSTR pszCertStoreName,
     return ret;
 }
 
+static const context_vtbl_t cert_vtbl;
+
+static void Cert_free(context_t *context)
+{
+    cert_t *cert = (cert_t*)context;
+
+    CryptMemFree(cert->ctx.pbCertEncoded);
+    LocalFree(cert->ctx.pCertInfo);
+}
+
+static context_t *Cert_clone(context_t *context, WINECRYPT_CERTSTORE *store, BOOL use_link)
+{
+    cert_t *cert;
+
+    if(use_link) {
+        cert = (cert_t*)Context_CreateLinkContext(sizeof(CERT_CONTEXT), context, store);
+        if(!cert)
+            return NULL;
+    }else {
+        const cert_t *cloned = (const cert_t*)context;
+        DWORD size = 0;
+        BOOL res;
+
+        cert = (cert_t*)Context_CreateDataContext(sizeof(CERT_CONTEXT), &cert_vtbl, store);
+        if(!cert)
+            return NULL;
+
+        Context_CopyProperties(&cert->ctx, &cloned->ctx);
+
+        cert->ctx.dwCertEncodingType = cloned->ctx.dwCertEncodingType;
+        cert->ctx.pbCertEncoded = CryptMemAlloc(cloned->ctx.cbCertEncoded);
+        memcpy(cert->ctx.pbCertEncoded, cloned->ctx.pbCertEncoded, cloned->ctx.cbCertEncoded);
+        cert->ctx.cbCertEncoded = cloned->ctx.cbCertEncoded;
+
+        /* FIXME: We don't need to decode the object here, we could just clone cert info. */
+        res = CryptDecodeObjectEx(cert->ctx.dwCertEncodingType, X509_CERT_TO_BE_SIGNED,
+         cert->ctx.pbCertEncoded, cert->ctx.cbCertEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL,
+         &cert->ctx.pCertInfo, &size);
+        if(!res) {
+            CertFreeCertificateContext(&cert->ctx);
+            return NULL;
+        }
+    }
+
+    cert->ctx.hCertStore = store;
+    return &cert->base;
+}
+
+static const context_vtbl_t cert_vtbl = {
+    Cert_free,
+    Cert_clone
+};
+
+static BOOL add_cert_to_store(WINECRYPT_CERTSTORE *store, const CERT_CONTEXT *cert,
+ DWORD add_disposition, BOOL use_link, PCCERT_CONTEXT *ret_context)
+{
+    const CERT_CONTEXT *existing = NULL;
+    BOOL ret = TRUE, inherit_props = FALSE;
+    context_t *new_context = NULL;
+
+    switch (add_disposition)
+    {
+    case CERT_STORE_ADD_ALWAYS:
+        break;
+    case CERT_STORE_ADD_NEW:
+    case CERT_STORE_ADD_REPLACE_EXISTING:
+    case CERT_STORE_ADD_REPLACE_EXISTING_INHERIT_PROPERTIES:
+    case CERT_STORE_ADD_USE_EXISTING:
+    case CERT_STORE_ADD_NEWER:
+    case CERT_STORE_ADD_NEWER_INHERIT_PROPERTIES:
+    {
+        BYTE hashToAdd[20];
+        DWORD size = sizeof(hashToAdd);
+
+        ret = CertGetCertificateContextProperty(cert, CERT_HASH_PROP_ID,
+         hashToAdd, &size);
+        if (ret)
+        {
+            CRYPT_HASH_BLOB blob = { sizeof(hashToAdd), hashToAdd };
+
+            existing = CertFindCertificateInStore(store, cert->dwCertEncodingType, 0,
+             CERT_FIND_SHA1_HASH, &blob, NULL);
+        }
+        break;
+    }
+    default:
+        FIXME("Unimplemented add disposition %d\n", add_disposition);
+        SetLastError(E_INVALIDARG);
+        return FALSE;
+    }
+
+    switch (add_disposition)
+    {
+    case CERT_STORE_ADD_ALWAYS:
+        break;
+    case CERT_STORE_ADD_NEW:
+        if (existing)
+        {
+            TRACE("found matching certificate, not adding\n");
+            SetLastError(CRYPT_E_EXISTS);
+            return FALSE;
+        }
+        break;
+    case CERT_STORE_ADD_REPLACE_EXISTING:
+        break;
+    case CERT_STORE_ADD_REPLACE_EXISTING_INHERIT_PROPERTIES:
+        if (use_link)
+            FIXME("CERT_STORE_ADD_REPLACE_EXISTING_INHERIT_PROPERTIES: semi-stub for links\n");
+        if (existing)
+            inherit_props = TRUE;
+        break;
+    case CERT_STORE_ADD_USE_EXISTING:
+        if(use_link)
+            FIXME("CERT_STORE_ADD_USE_EXISTING: semi-stub for links\n");
+        if (existing)
+        {
+            Context_CopyProperties(existing, cert);
+            if (ret_context)
+                *ret_context = CertDuplicateCertificateContext(existing);
+            return TRUE;
+        }
+        break;
+    case CERT_STORE_ADD_NEWER:
+        if (existing && CompareFileTime(&existing->pCertInfo->NotBefore, &cert->pCertInfo->NotBefore) >= 0)
+        {
+            TRACE("existing certificate is newer, not adding\n");
+            SetLastError(CRYPT_E_EXISTS);
+            return FALSE;
+        }
+        break;
+    case CERT_STORE_ADD_NEWER_INHERIT_PROPERTIES:
+        if (existing)
+        {
+            if (CompareFileTime(&existing->pCertInfo->NotBefore, &cert->pCertInfo->NotBefore) >= 0)
+            {
+                TRACE("existing certificate is newer, not adding\n");
+                SetLastError(CRYPT_E_EXISTS);
+                return FALSE;
+            }
+            inherit_props = TRUE;
+        }
+        break;
+    }
+
+    /* FIXME: We have tests that this works, but what should we really do in this case? */
+    if(!store) {
+        if(ret_context)
+            *ret_context = CertDuplicateCertificateContext(cert);
+        return TRUE;
+    }
+
+    ret = store->vtbl->certs.addContext(store, context_from_ptr(cert), existing ? context_from_ptr(existing) : NULL,
+     (ret_context || inherit_props) ? &new_context : NULL, use_link);
+    if(!ret)
+        return FALSE;
+
+    if(inherit_props)
+        Context_CopyProperties(context_ptr(new_context), existing);
+
+    if(ret_context)
+        *ret_context = context_ptr(new_context);
+    else if(new_context)
+        Context_Release(new_context);
+
+    TRACE("returning %d\n", ret);
+    return ret;
+}
+
+BOOL WINAPI CertAddCertificateContextToStore(HCERTSTORE hCertStore, PCCERT_CONTEXT pCertContext,
+ DWORD dwAddDisposition, PCCERT_CONTEXT *ppStoreContext)
+{
+    WINECRYPT_CERTSTORE *store = hCertStore;
+
+    TRACE("(%p, %p, %08x, %p)\n", hCertStore, pCertContext, dwAddDisposition, ppStoreContext);
+
+    return add_cert_to_store(store, pCertContext, dwAddDisposition, FALSE, ppStoreContext);
+}
+
 BOOL WINAPI CertAddCertificateLinkToStore(HCERTSTORE hCertStore,
  PCCERT_CONTEXT pCertContext, DWORD dwAddDisposition,
  PCCERT_CONTEXT *ppCertContext)
 {
     static int calls;
-    PWINECRYPT_CERTSTORE store = (PWINECRYPT_CERTSTORE)hCertStore;
+    WINECRYPT_CERTSTORE *store = (WINECRYPT_CERTSTORE*)hCertStore;
 
     if (!(calls++))
         FIXME("(%p, %p, %08x, %p): semi-stub\n", hCertStore, pCertContext,
@@ -117,14 +295,14 @@ BOOL WINAPI CertAddCertificateLinkToStore(HCERTSTORE hCertStore,
         SetLastError(E_INVALIDARG);
         return FALSE;
     }
-    return CertAddCertificateContextToStore(hCertStore, pCertContext,
-     dwAddDisposition, ppCertContext);
+    return add_cert_to_store(hCertStore, pCertContext, dwAddDisposition, TRUE, ppCertContext);
 }
 
 PCCERT_CONTEXT WINAPI CertCreateCertificateContext(DWORD dwCertEncodingType,
  const BYTE *pbCertEncoded, DWORD cbCertEncoded)
 {
-    PCERT_CONTEXT cert = NULL;
+    cert_t *cert = NULL;
+    BYTE *data = NULL;
     BOOL ret;
     PCERT_INFO certInfo = NULL;
     DWORD size = 0;
@@ -141,81 +319,65 @@ PCCERT_CONTEXT WINAPI CertCreateCertificateContext(DWORD dwCertEncodingType,
     ret = CryptDecodeObjectEx(dwCertEncodingType, X509_CERT_TO_BE_SIGNED,
      pbCertEncoded, cbCertEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL,
      &certInfo, &size);
-    if (ret)
-    {
-        BYTE *data = NULL;
+    if (!ret)
+        return NULL;
 
-        cert = Context_CreateDataContext(sizeof(CERT_CONTEXT));
-        if (!cert)
-            goto end;
-        data = CryptMemAlloc(cbCertEncoded);
-        if (!data)
-        {
-            CertFreeCertificateContext(cert);
-            cert = NULL;
-            goto end;
-        }
-        memcpy(data, pbCertEncoded, cbCertEncoded);
-        cert->dwCertEncodingType = dwCertEncodingType;
-        cert->pbCertEncoded      = data;
-        cert->cbCertEncoded      = cbCertEncoded;
-        cert->pCertInfo          = certInfo;
-        cert->hCertStore         = 0;
+    cert = (cert_t*)Context_CreateDataContext(sizeof(CERT_CONTEXT), &cert_vtbl, &empty_store);
+    if (!cert)
+        return NULL;
+    data = CryptMemAlloc(cbCertEncoded);
+    if (!data)
+    {
+        Context_Release(&cert->base);
+        return NULL;
     }
 
-end:
-    return cert;
+    memcpy(data, pbCertEncoded, cbCertEncoded);
+    cert->ctx.dwCertEncodingType = dwCertEncodingType;
+    cert->ctx.pbCertEncoded      = data;
+    cert->ctx.cbCertEncoded      = cbCertEncoded;
+    cert->ctx.pCertInfo          = certInfo;
+    cert->ctx.hCertStore         = &empty_store;
+
+    return &cert->ctx;
 }
 
-PCCERT_CONTEXT WINAPI CertDuplicateCertificateContext(
- PCCERT_CONTEXT pCertContext)
+PCCERT_CONTEXT WINAPI CertDuplicateCertificateContext(PCCERT_CONTEXT pCertContext)
 {
     TRACE("(%p)\n", pCertContext);
 
     if (!pCertContext)
         return NULL;
 
-    Context_AddRef((void *)pCertContext, sizeof(CERT_CONTEXT));
+    Context_AddRef(&cert_from_ptr(pCertContext)->base);
     return pCertContext;
 }
 
-static void CertDataContext_Free(void *context)
-{
-    PCERT_CONTEXT certContext = context;
-
-    CryptMemFree(certContext->pbCertEncoded);
-    LocalFree(certContext->pCertInfo);
-}
-
 BOOL WINAPI CertFreeCertificateContext(PCCERT_CONTEXT pCertContext)
 {
-    BOOL ret = TRUE;
-
     TRACE("(%p)\n", pCertContext);
 
     if (pCertContext)
-        ret = Context_Release((void *)pCertContext, sizeof(CERT_CONTEXT),
-         CertDataContext_Free);
-    return ret;
+        Context_Release(&cert_from_ptr(pCertContext)->base);
+    return TRUE;
 }
 
 DWORD WINAPI CertEnumCertificateContextProperties(PCCERT_CONTEXT pCertContext,
  DWORD dwPropId)
 {
-    PCONTEXT_PROPERTY_LIST properties = Context_GetProperties(
-     pCertContext, sizeof(CERT_CONTEXT));
+    cert_t *cert = cert_from_ptr(pCertContext);
     DWORD ret;
 
     TRACE("(%p, %d)\n", pCertContext, dwPropId);
 
-    if (properties)
-        ret = ContextPropertyList_EnumPropIDs(properties, dwPropId);
+    if (cert->base.properties)
+        ret = ContextPropertyList_EnumPropIDs(cert->base.properties, dwPropId);
     else
         ret = 0;
     return ret;
 }
 
-static BOOL CertContext_GetHashProp(void *context, DWORD dwPropId,
+static BOOL CertContext_GetHashProp(cert_t *cert, DWORD dwPropId,
  ALG_ID algID, const BYTE *toHash, DWORD toHashLen, void *pvData,
  DWORD *pcbData)
 {
@@ -225,7 +387,7 @@ static BOOL CertContext_GetHashProp(void *context, DWORD dwPropId,
     {
         CRYPT_DATA_BLOB blob = { *pcbData, pvData };
 
-        ret = CertContext_SetProperty(context, dwPropId, 0, &blob);
+        ret = CertContext_SetProperty(cert, dwPropId, 0, &blob);
     }
     return ret;
 }
@@ -251,19 +413,16 @@ static BOOL CertContext_CopyParam(void *pvData, DWORD *pcbData, const void *pb,
     return ret;
 }
 
-static BOOL CertContext_GetProperty(void *context, DWORD dwPropId,
+static BOOL CertContext_GetProperty(cert_t *cert, DWORD dwPropId,
  void *pvData, DWORD *pcbData)
 {
-    PCCERT_CONTEXT pCertContext = context;
-    PCONTEXT_PROPERTY_LIST properties =
-     Context_GetProperties(context, sizeof(CERT_CONTEXT));
     BOOL ret;
     CRYPT_DATA_BLOB blob;
 
-    TRACE("(%p, %d, %p, %p)\n", context, dwPropId, pvData, pcbData);
+    TRACE("(%p, %d, %p, %p)\n", cert, dwPropId, pvData, pcbData);
 
-    if (properties)
-        ret = ContextPropertyList_FindProperty(properties, dwPropId, &blob);
+    if (cert->base.properties)
+        ret = ContextPropertyList_FindProperty(cert->base.properties, dwPropId, &blob);
     else
         ret = FALSE;
     if (ret)
@@ -274,49 +433,49 @@ static BOOL CertContext_GetProperty(void *context, DWORD dwPropId,
         switch (dwPropId)
         {
         case CERT_SHA1_HASH_PROP_ID:
-            ret = CertContext_GetHashProp(context, dwPropId, CALG_SHA1,
-             pCertContext->pbCertEncoded, pCertContext->cbCertEncoded, pvData,
+            ret = CertContext_GetHashProp(cert, dwPropId, CALG_SHA1,
+             cert->ctx.pbCertEncoded, cert->ctx.cbCertEncoded, pvData,
              pcbData);
             break;
         case CERT_MD5_HASH_PROP_ID:
-            ret = CertContext_GetHashProp(context, dwPropId, CALG_MD5,
-             pCertContext->pbCertEncoded, pCertContext->cbCertEncoded, pvData,
+            ret = CertContext_GetHashProp(cert, dwPropId, CALG_MD5,
+             cert->ctx.pbCertEncoded, cert->ctx.cbCertEncoded, pvData,
              pcbData);
             break;
         case CERT_SUBJECT_NAME_MD5_HASH_PROP_ID:
-            ret = CertContext_GetHashProp(context, dwPropId, CALG_MD5,
-             pCertContext->pCertInfo->Subject.pbData,
-             pCertContext->pCertInfo->Subject.cbData,
+            ret = CertContext_GetHashProp(cert, dwPropId, CALG_MD5,
+             cert->ctx.pCertInfo->Subject.pbData,
+             cert->ctx.pCertInfo->Subject.cbData,
              pvData, pcbData);
             break;
         case CERT_SUBJECT_PUBLIC_KEY_MD5_HASH_PROP_ID:
-            ret = CertContext_GetHashProp(context, dwPropId, CALG_MD5,
-             pCertContext->pCertInfo->SubjectPublicKeyInfo.PublicKey.pbData,
-             pCertContext->pCertInfo->SubjectPublicKeyInfo.PublicKey.cbData,
+            ret = CertContext_GetHashProp(cert, dwPropId, CALG_MD5,
+             cert->ctx.pCertInfo->SubjectPublicKeyInfo.PublicKey.pbData,
+             cert->ctx.pCertInfo->SubjectPublicKeyInfo.PublicKey.cbData,
              pvData, pcbData);
             break;
         case CERT_ISSUER_SERIAL_NUMBER_MD5_HASH_PROP_ID:
-            ret = CertContext_GetHashProp(context, dwPropId, CALG_MD5,
-             pCertContext->pCertInfo->SerialNumber.pbData,
-             pCertContext->pCertInfo->SerialNumber.cbData,
+            ret = CertContext_GetHashProp(cert, dwPropId, CALG_MD5,
+             cert->ctx.pCertInfo->SerialNumber.pbData,
+             cert->ctx.pCertInfo->SerialNumber.cbData,
              pvData, pcbData);
             break;
         case CERT_SIGNATURE_HASH_PROP_ID:
-            ret = CryptHashToBeSigned(0, pCertContext->dwCertEncodingType,
-             pCertContext->pbCertEncoded, pCertContext->cbCertEncoded, pvData,
+            ret = CryptHashToBeSigned(0, cert->ctx.dwCertEncodingType,
+             cert->ctx.pbCertEncoded, cert->ctx.cbCertEncoded, pvData,
              pcbData);
             if (ret && pvData)
             {
                 CRYPT_DATA_BLOB blob = { *pcbData, pvData };
 
-                ret = CertContext_SetProperty(context, dwPropId, 0, &blob);
+                ret = CertContext_SetProperty(cert, dwPropId, 0, &blob);
             }
             break;
         case CERT_KEY_IDENTIFIER_PROP_ID:
         {
             PCERT_EXTENSION ext = CertFindExtension(
-             szOID_SUBJECT_KEY_IDENTIFIER, pCertContext->pCertInfo->cExtension,
-             pCertContext->pCertInfo->rgExtension);
+             szOID_SUBJECT_KEY_IDENTIFIER, cert->ctx.pCertInfo->cExtension,
+             cert->ctx.pCertInfo->rgExtension);
 
             if (ext)
             {
@@ -331,7 +490,7 @@ static BOOL CertContext_GetProperty(void *context, DWORD dwPropId,
                 {
                     ret = CertContext_CopyParam(pvData, pcbData, value.pbData,
                      value.cbData);
-                    CertContext_SetProperty(context, dwPropId, 0, &value);
+                    CertContext_SetProperty(cert, dwPropId, 0, &value);
                 }
             }
             else
@@ -372,6 +531,7 @@ void CRYPT_FixKeyProvInfoPointers(PCRYPT_KEY_PROV_INFO info)
 BOOL WINAPI CertGetCertificateContextProperty(PCCERT_CONTEXT pCertContext,
  DWORD dwPropId, void *pvData, DWORD *pcbData)
 {
+    cert_t *cert = cert_from_ptr(pCertContext);
     BOOL ret;
 
     TRACE("(%p, %d, %p, %p)\n", pCertContext, dwPropId, pvData, pcbData);
@@ -386,22 +546,14 @@ BOOL WINAPI CertGetCertificateContextProperty(PCCERT_CONTEXT pCertContext,
         ret = FALSE;
         break;
     case CERT_ACCESS_STATE_PROP_ID:
-        if (pCertContext->hCertStore)
-            ret = CertGetStoreProperty(pCertContext->hCertStore, dwPropId,
-             pvData, pcbData);
-        else
-        {
-            DWORD state = 0;
-
-            ret = CertContext_CopyParam(pvData, pcbData, &state, sizeof(state));
-        }
+        ret = CertGetStoreProperty(cert->ctx.hCertStore, dwPropId, pvData, pcbData);
         break;
     case CERT_KEY_PROV_HANDLE_PROP_ID:
     {
         CERT_KEY_CONTEXT keyContext;
         DWORD size = sizeof(keyContext);
 
-        ret = CertContext_GetProperty((void *)pCertContext,
+        ret = CertContext_GetProperty(cert,
          CERT_KEY_CONTEXT_PROP_ID, &keyContext, &size);
         if (ret)
             ret = CertContext_CopyParam(pvData, pcbData, &keyContext.hCryptProv,
@@ -409,13 +561,13 @@ BOOL WINAPI CertGetCertificateContextProperty(PCCERT_CONTEXT pCertContext,
         break;
     }
     case CERT_KEY_PROV_INFO_PROP_ID:
-        ret = CertContext_GetProperty((void *)pCertContext, dwPropId, pvData,
+        ret = CertContext_GetProperty(cert, dwPropId, pvData,
          pcbData);
         if (ret && pvData)
             CRYPT_FixKeyProvInfoPointers(pvData);
         break;
     default:
-        ret = CertContext_GetProperty((void *)pCertContext, dwPropId, pvData,
+        ret = CertContext_GetProperty(cert, dwPropId, pvData,
          pcbData);
     }
 
@@ -472,7 +624,7 @@ static void CRYPT_CopyKeyProvInfo(PCRYPT_KEY_PROV_INFO to,
     }
 }
 
-static BOOL CertContext_SetKeyProvInfoProperty(PCONTEXT_PROPERTY_LIST properties,
+static BOOL CertContext_SetKeyProvInfoProperty(CONTEXT_PROPERTY_LIST *properties,
  const CRYPT_KEY_PROV_INFO *info)
 {
     BOOL ret;
@@ -503,16 +655,14 @@ static BOOL CertContext_SetKeyProvInfoProperty(PCONTEXT_PROPERTY_LIST properties
     return ret;
 }
 
-static BOOL CertContext_SetProperty(void *context, DWORD dwPropId,
+static BOOL CertContext_SetProperty(cert_t *cert, DWORD dwPropId,
  DWORD dwFlags, const void *pvData)
 {
-    PCONTEXT_PROPERTY_LIST properties =
-     Context_GetProperties(context, sizeof(CERT_CONTEXT));
     BOOL ret;
 
-    TRACE("(%p, %d, %08x, %p)\n", context, dwPropId, dwFlags, pvData);
+    TRACE("(%p, %d, %08x, %p)\n", cert, dwPropId, dwFlags, pvData);
 
-    if (!properties)
+    if (!cert->base.properties)
         ret = FALSE;
     else
     {
@@ -541,23 +691,23 @@ static BOOL CertContext_SetProperty(void *context, DWORD dwPropId,
             {
                 const CRYPT_DATA_BLOB *blob = pvData;
 
-                ret = ContextPropertyList_SetProperty(properties, dwPropId,
+                ret = ContextPropertyList_SetProperty(cert->base.properties, dwPropId,
                  blob->pbData, blob->cbData);
             }
             else
             {
-                ContextPropertyList_RemoveProperty(properties, dwPropId);
+                ContextPropertyList_RemoveProperty(cert->base.properties, dwPropId);
                 ret = TRUE;
             }
             break;
         }
         case CERT_DATE_STAMP_PROP_ID:
             if (pvData)
-                ret = ContextPropertyList_SetProperty(properties, dwPropId,
+                ret = ContextPropertyList_SetProperty(cert->base.properties, dwPropId,
                  pvData, sizeof(FILETIME));
             else
             {
-                ContextPropertyList_RemoveProperty(properties, dwPropId);
+                ContextPropertyList_RemoveProperty(cert->base.properties, dwPropId);
                 ret = TRUE;
             }
             break;
@@ -573,22 +723,22 @@ static BOOL CertContext_SetProperty(void *context, DWORD dwPropId,
                     ret = FALSE;
                 }
                 else
-                    ret = ContextPropertyList_SetProperty(properties, dwPropId,
+                    ret = ContextPropertyList_SetProperty(cert->base.properties, dwPropId,
                      (const BYTE *)keyContext, keyContext->cbSize);
             }
             else
             {
-                ContextPropertyList_RemoveProperty(properties, dwPropId);
+                ContextPropertyList_RemoveProperty(cert->base.properties, dwPropId);
                 ret = TRUE;
             }
             break;
         }
         case CERT_KEY_PROV_INFO_PROP_ID:
             if (pvData)
-                ret = CertContext_SetKeyProvInfoProperty(properties, pvData);
+                ret = CertContext_SetKeyProvInfoProperty(cert->base.properties, pvData);
             else
             {
-                ContextPropertyList_RemoveProperty(properties, dwPropId);
+                ContextPropertyList_RemoveProperty(cert->base.properties, dwPropId);
                 ret = TRUE;
             }
             break;
@@ -597,7 +747,7 @@ static BOOL CertContext_SetProperty(void *context, DWORD dwPropId,
             CERT_KEY_CONTEXT keyContext;
             DWORD size = sizeof(keyContext);
 
-            ret = CertContext_GetProperty(context, CERT_KEY_CONTEXT_PROP_ID,
+            ret = CertContext_GetProperty(cert, CERT_KEY_CONTEXT_PROP_ID,
              &keyContext, &size);
             if (ret)
             {
@@ -612,7 +762,7 @@ static BOOL CertContext_SetProperty(void *context, DWORD dwPropId,
                 keyContext.hCryptProv = 0;
                 keyContext.dwKeySpec = AT_SIGNATURE;
             }
-            ret = CertContext_SetProperty(context, CERT_KEY_CONTEXT_PROP_ID,
+            ret = CertContext_SetProperty(cert, CERT_KEY_CONTEXT_PROP_ID,
              0, &keyContext);
             break;
         }
@@ -645,7 +795,7 @@ BOOL WINAPI CertSetCertificateContextProperty(PCCERT_CONTEXT pCertContext,
         SetLastError(E_INVALIDARG);
         return FALSE;
     }
-    ret = CertContext_SetProperty((void *)pCertContext, dwPropId, dwFlags,
+    ret = CertContext_SetProperty(cert_from_ptr(pCertContext), dwPropId, dwFlags,
      pvData);
     TRACE("returning %d\n", ret);
     return ret;
@@ -1307,6 +1457,8 @@ static BOOL compare_cert_by_cert_id(PCCERT_CONTEXT pCertContext, DWORD dwType,
                 ret = !memcmp(buf, id->u.KeyId.pbData, size);
                 CryptMemFree(buf);
             }
+            else
+                ret = FALSE;
         }
         else
             ret = FALSE;
@@ -1347,6 +1499,8 @@ static BOOL compare_cert_by_signature_hash(PCCERT_CONTEXT pCertContext, DWORD dw
             ret = !memcmp(buf, hash->pbData, size);
             CryptMemFree(buf);
         }
+        else
+            ret = FALSE;
     }
     else
         ret = FALSE;
@@ -1730,7 +1884,7 @@ typedef struct _OLD_CERT_REVOCATION_STATUS {
     DWORD dwIndex;
     DWORD dwError;
     DWORD dwReason;
-} OLD_CERT_REVOCATION_STATUS, *POLD_CERT_REVOCATION_STATUS;
+} OLD_CERT_REVOCATION_STATUS;
 
 typedef BOOL (WINAPI *CertVerifyRevocationFunc)(DWORD, DWORD, DWORD,
  void **, DWORD, PCERT_REVOCATION_PARA, PCERT_REVOCATION_STATUS);
@@ -2216,10 +2370,14 @@ BOOL WINAPI CryptSignAndEncodeCertificate(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCrypt
                         }
                         CryptMemFree(hash);
                     }
+                    else
+                        ret = FALSE;
                 }
             }
             CryptMemFree(encoded);
         }
+        else
+            ret = FALSE;
     }
     return ret;
 }
index 0222b34..0aa359f 100644 (file)
@@ -26,8 +26,6 @@ WINE_DECLARE_DEBUG_CHANNEL(chain);
 
 #define DEFAULT_CYCLE_MODULUS 7
 
-static HCERTCHAINENGINE CRYPT_defaultChainEngine;
-
 /* This represents a subset of a certificate chain engine:  it doesn't include
  * the "hOther" store described by MSDN, because I'm not sure how that's used.
  * It also doesn't include the "hTrust" store, because I don't yet implement
@@ -42,7 +40,7 @@ typedef struct _CertificateChainEngine
     DWORD      dwUrlRetrievalTimeout;
     DWORD      MaximumCachedCertificates;
     DWORD      CycleDetectionModulus;
-} CertificateChainEngine, *PCertificateChainEngine;
+} CertificateChainEngine;
 
 static inline void CRYPT_AddStoresToCollection(HCERTSTORE collection,
  DWORD cStores, HCERTSTORE *stores)
@@ -107,45 +105,102 @@ static BOOL CRYPT_CheckRestrictedRoot(HCERTSTORE store)
     return ret;
 }
 
-HCERTCHAINENGINE CRYPT_CreateChainEngine(HCERTSTORE root,
- PCERT_CHAIN_ENGINE_CONFIG pConfig)
+HCERTCHAINENGINE CRYPT_CreateChainEngine(HCERTSTORE root, DWORD system_store, const CERT_CHAIN_ENGINE_CONFIG *config)
 {
+    CertificateChainEngine *engine;
+    HCERTSTORE worldStores[4];
+
     static const WCHAR caW[] = { 'C','A',0 };
     static const WCHAR myW[] = { 'M','y',0 };
     static const WCHAR trustW[] = { 'T','r','u','s','t',0 };
-    PCertificateChainEngine engine =
-     CryptMemAlloc(sizeof(CertificateChainEngine));
-
-    if (engine)
-    {
-        HCERTSTORE worldStores[4];
-
-        engine->ref = 1;
-        engine->hRoot = root;
-        engine->hWorld = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0,
-         CERT_STORE_CREATE_NEW_FLAG, NULL);
-        worldStores[0] = CertDuplicateStore(engine->hRoot);
-        worldStores[1] = CertOpenSystemStoreW(0, caW);
-        worldStores[2] = CertOpenSystemStoreW(0, myW);
-        worldStores[3] = CertOpenSystemStoreW(0, trustW);
-        CRYPT_AddStoresToCollection(engine->hWorld,
-         sizeof(worldStores) / sizeof(worldStores[0]), worldStores);
-        CRYPT_AddStoresToCollection(engine->hWorld,
-         pConfig->cAdditionalStore, pConfig->rghAdditionalStore);
-        CRYPT_CloseStores(sizeof(worldStores) / sizeof(worldStores[0]),
-         worldStores);
-        engine->dwFlags = pConfig->dwFlags;
-        engine->dwUrlRetrievalTimeout = pConfig->dwUrlRetrievalTimeout;
-        engine->MaximumCachedCertificates =
-         pConfig->MaximumCachedCertificates;
-        if (pConfig->CycleDetectionModulus)
-            engine->CycleDetectionModulus = pConfig->CycleDetectionModulus;
+
+    if(!root) {
+        if(config->cbSize >= sizeof(CERT_CHAIN_ENGINE_CONFIG) && config->hExclusiveRoot)
+            root = CertDuplicateStore(config->hExclusiveRoot);
+        else if (config->hRestrictedRoot)
+            root = CertDuplicateStore(config->hRestrictedRoot);
         else
-            engine->CycleDetectionModulus = DEFAULT_CYCLE_MODULUS;
-    }
+            root = CertOpenStore(CERT_STORE_PROV_SYSTEM_W, 0, 0, system_store, rootW);
+        if(!root)
+            return NULL;
+    }
+
+    engine = CryptMemAlloc(sizeof(CertificateChainEngine));
+    if(!engine) {
+        CertCloseStore(root, 0);
+        return NULL;
+    }
+
+    engine->ref = 1;
+    engine->hRoot = root;
+    engine->hWorld = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0, CERT_STORE_CREATE_NEW_FLAG, NULL);
+    worldStores[0] = CertDuplicateStore(engine->hRoot);
+    worldStores[1] = CertOpenStore(CERT_STORE_PROV_SYSTEM_W, 0, 0, system_store, caW);
+    worldStores[2] = CertOpenStore(CERT_STORE_PROV_SYSTEM_W, 0, 0, system_store, myW);
+    worldStores[3] = CertOpenStore(CERT_STORE_PROV_SYSTEM_W, 0, 0, system_store, trustW);
+
+    CRYPT_AddStoresToCollection(engine->hWorld,  sizeof(worldStores) / sizeof(worldStores[0]), worldStores);
+    CRYPT_AddStoresToCollection(engine->hWorld,  config->cAdditionalStore, config->rghAdditionalStore);
+    CRYPT_CloseStores(sizeof(worldStores) / sizeof(worldStores[0]), worldStores);
+
+    engine->dwFlags = config->dwFlags;
+    engine->dwUrlRetrievalTimeout = config->dwUrlRetrievalTimeout;
+    engine->MaximumCachedCertificates = config->MaximumCachedCertificates;
+    if(config->CycleDetectionModulus)
+        engine->CycleDetectionModulus = config->CycleDetectionModulus;
+    else
+        engine->CycleDetectionModulus = DEFAULT_CYCLE_MODULUS;
+
     return engine;
 }
 
+static CertificateChainEngine *default_cu_engine, *default_lm_engine;
+
+static CertificateChainEngine *get_chain_engine(HCERTCHAINENGINE handle, BOOL allow_default)
+{
+    const CERT_CHAIN_ENGINE_CONFIG config = { sizeof(config) };
+
+    if(handle == HCCE_CURRENT_USER) {
+        if(!allow_default)
+            return NULL;
+
+        if(!default_cu_engine) {
+            handle = CRYPT_CreateChainEngine(NULL, CERT_SYSTEM_STORE_CURRENT_USER, &config);
+            InterlockedCompareExchangePointer((void**)&default_cu_engine, handle, NULL);
+            if(default_cu_engine != handle)
+                CertFreeCertificateChainEngine(handle);
+        }
+
+        return default_cu_engine;
+    }
+
+    if(handle == HCCE_LOCAL_MACHINE) {
+        if(!allow_default)
+            return NULL;
+
+        if(!default_lm_engine) {
+            handle = CRYPT_CreateChainEngine(NULL, CERT_SYSTEM_STORE_LOCAL_MACHINE, &config);
+            InterlockedCompareExchangePointer((void**)&default_lm_engine, handle, NULL);
+            if(default_lm_engine != handle)
+                CertFreeCertificateChainEngine(handle);
+        }
+
+        return default_lm_engine;
+    }
+
+    return (CertificateChainEngine*)handle;
+}
+
+static void free_chain_engine(CertificateChainEngine *engine)
+{
+    if(!engine || InterlockedDecrement(&engine->ref))
+        return;
+
+    CertCloseStore(engine->hWorld, 0);
+    CertCloseStore(engine->hRoot, 0);
+    CryptMemFree(engine);
+}
+
 typedef struct _CERT_CHAIN_ENGINE_CONFIG_NO_EXCLUSIVE_ROOT
 {
     DWORD       cbSize;
@@ -173,66 +228,27 @@ BOOL WINAPI CertCreateCertificateChainEngine(PCERT_CHAIN_ENGINE_CONFIG pConfig,
         SetLastError(E_INVALIDARG);
         return FALSE;
     }
-    *phChainEngine = NULL;
     ret = CRYPT_CheckRestrictedRoot(pConfig->hRestrictedRoot);
-    if (ret)
+    if (!ret)
     {
-        HCERTSTORE root;
-        HCERTCHAINENGINE engine;
-
-        if (pConfig->cbSize >= sizeof(CERT_CHAIN_ENGINE_CONFIG) &&
-         pConfig->hExclusiveRoot)
-            root = CertDuplicateStore(pConfig->hExclusiveRoot);
-        else if (pConfig->hRestrictedRoot)
-            root = CertDuplicateStore(pConfig->hRestrictedRoot);
-        else
-            root = CertOpenSystemStoreW(0, rootW);
-        engine = CRYPT_CreateChainEngine(root, pConfig);
-        if (engine)
-        {
-            *phChainEngine = engine;
-            ret = TRUE;
-        }
-        else
-            ret = FALSE;
+        *phChainEngine = NULL;
+        return FALSE;
     }
-    return ret;
-}
 
-VOID WINAPI CertFreeCertificateChainEngine(HCERTCHAINENGINE hChainEngine)
-{
-    PCertificateChainEngine engine = (PCertificateChainEngine)hChainEngine;
-
-    TRACE("(%p)\n", hChainEngine);
-
-    if (engine && InterlockedDecrement(&engine->ref) == 0)
-    {
-        CertCloseStore(engine->hWorld, 0);
-        CertCloseStore(engine->hRoot, 0);
-        CryptMemFree(engine);
-    }
+    *phChainEngine = CRYPT_CreateChainEngine(NULL, CERT_SYSTEM_STORE_CURRENT_USER, pConfig);
+    return *phChainEngine != NULL;
 }
 
-static HCERTCHAINENGINE CRYPT_GetDefaultChainEngine(void)
+void WINAPI CertFreeCertificateChainEngine(HCERTCHAINENGINE hChainEngine)
 {
-    if (!CRYPT_defaultChainEngine)
-    {
-        CERT_CHAIN_ENGINE_CONFIG config = { 0 };
-        HCERTCHAINENGINE engine;
-
-        config.cbSize = sizeof(config);
-        CertCreateCertificateChainEngine(&config, &engine);
-        InterlockedCompareExchangePointer(&CRYPT_defaultChainEngine, engine,
-         NULL);
-        if (CRYPT_defaultChainEngine != engine)
-            CertFreeCertificateChainEngine(engine);
-    }
-    return CRYPT_defaultChainEngine;
+    TRACE("(%p)\n", hChainEngine);
+    free_chain_engine(get_chain_engine(hChainEngine, FALSE));
 }
 
 void default_chain_engine_free(void)
 {
-    CertFreeCertificateChainEngine(CRYPT_defaultChainEngine);
+    free_chain_engine(default_cu_engine);
+    free_chain_engine(default_lm_engine);
 }
 
 typedef struct _CertificateChain
@@ -240,7 +256,7 @@ typedef struct _CertificateChain
     CERT_CHAIN_CONTEXT context;
     HCERTSTORE world;
     LONG ref;
-} CertificateChain, *PCertificateChain;
+} CertificateChain;
 
 static BOOL CRYPT_IsCertificateSelfSigned(PCCERT_CONTEXT cert)
 {
@@ -299,6 +315,8 @@ static BOOL CRYPT_IsCertificateSelfSigned(PCCERT_CONTEXT cert)
                         ret = !memcmp(buf, info->KeyId.pbData, size);
                         CryptMemFree(buf);
                     }
+                    else
+                        ret = FALSE;
                 }
                 else
                     ret = FALSE;
@@ -470,7 +488,7 @@ static void CRYPT_CheckTrustedStatus(HCERTSTORE hRoot,
         CertFreeCertificateContext(trustedRoot);
 }
 
-static void CRYPT_CheckRootCert(HCERTCHAINENGINE hRoot,
+static void CRYPT_CheckRootCert(HCERTSTORE hRoot,
  PCERT_CHAIN_ELEMENT rootElement)
 {
     PCCERT_CONTEXT root = rootElement->pCertContext;
@@ -559,7 +577,7 @@ static BOOL CRYPT_DecodeBasicConstraints(PCCERT_CONTEXT cert,
  * Returns TRUE if the element can be a CA, and the length of the remaining
  * chain is valid.
  */
-static BOOL CRYPT_CheckBasicConstraintsForCA(PCertificateChainEngine engine,
+static BOOL CRYPT_CheckBasicConstraintsForCA(CertificateChainEngine *engine,
  PCCERT_CONTEXT cert, CERT_BASIC_CONSTRAINTS2_INFO *chainConstraints,
  DWORD remainingCAs, BOOL isRoot, BOOL *pathLengthConstraintViolated)
 {
@@ -1705,7 +1723,7 @@ static void dump_element(PCCERT_CONTEXT cert)
         dump_extension(&cert->pCertInfo->rgExtension[i]);
 }
 
-static BOOL CRYPT_KeyUsageValid(PCertificateChainEngine engine,
+static BOOL CRYPT_KeyUsageValid(CertificateChainEngine *engine,
  PCCERT_CONTEXT cert, BOOL isRoot, BOOL isCA, DWORD index)
 {
     PCERT_EXTENSION ext;
@@ -1861,7 +1879,7 @@ static BOOL CRYPT_IsCertVersionValid(PCCERT_CONTEXT cert)
     return ret;
 }
 
-static void CRYPT_CheckSimpleChain(PCertificateChainEngine engine,
+static void CRYPT_CheckSimpleChain(CertificateChainEngine *engine,
  PCERT_SIMPLE_CHAIN chain, LPFILETIME time)
 {
     PCERT_CHAIN_ELEMENT rootElement = chain->rgpElement[chain->cElement - 1];
@@ -1964,8 +1982,83 @@ static void CRYPT_CheckSimpleChain(PCertificateChainEngine engine,
     CRYPT_CombineTrustStatus(&chain->TrustStatus, &rootElement->TrustStatus);
 }
 
-static PCCERT_CONTEXT CRYPT_GetIssuer(HCERTSTORE store, PCCERT_CONTEXT subject,
- PCCERT_CONTEXT prevIssuer, DWORD *infoStatus)
+static PCCERT_CONTEXT CRYPT_FindIssuer(const CertificateChainEngine *engine, const CERT_CONTEXT *cert,
+        HCERTSTORE store, DWORD type, void *para, DWORD flags, PCCERT_CONTEXT prev_issuer)
+{
+    CRYPT_URL_ARRAY *urls;
+    PCCERT_CONTEXT issuer;
+    DWORD size;
+    BOOL res;
+
+    issuer = CertFindCertificateInStore(store, cert->dwCertEncodingType, 0, type, para, prev_issuer);
+    if(issuer) {
+        TRACE("Found in store %p\n", issuer);
+        return issuer;
+    }
+
+    /* FIXME: For alternate issuers, we don't search world store nor try to retrieve issuer from URL.
+     * This needs more tests.
+     */
+    if(prev_issuer)
+        return NULL;
+
+    if(engine->hWorld) {
+        issuer = CertFindCertificateInStore(engine->hWorld, cert->dwCertEncodingType, 0, type, para, NULL);
+        if(issuer) {
+            TRACE("Found in world %p\n", issuer);
+            return issuer;
+        }
+    }
+
+    res = CryptGetObjectUrl(URL_OID_CERTIFICATE_ISSUER, (void*)cert, 0, NULL, &size, NULL, NULL, NULL);
+    if(!res)
+        return NULL;
+
+    urls = HeapAlloc(GetProcessHeap(), 0, size);
+    if(!urls)
+        return NULL;
+
+    res = CryptGetObjectUrl(URL_OID_CERTIFICATE_ISSUER, (void*)cert, 0, urls, &size, NULL, NULL, NULL);
+    if(res)
+    {
+        CERT_CONTEXT *new_cert;
+        HCERTSTORE new_store;
+        unsigned i;
+
+        for(i=0; i < urls->cUrl; i++)
+        {
+            TRACE("Trying URL %s\n", debugstr_w(urls->rgwszUrl[i]));
+
+            res = CryptRetrieveObjectByUrlW(urls->rgwszUrl[i], CONTEXT_OID_CERTIFICATE,
+             (flags & CERT_CHAIN_CACHE_ONLY_URL_RETRIEVAL) ? CRYPT_CACHE_ONLY_RETRIEVAL : CRYPT_AIA_RETRIEVAL,
+             0, (void**)&new_cert, NULL, NULL, NULL, NULL);
+            if(!res)
+            {
+                TRACE("CryptRetrieveObjectByUrlW failed: %u\n", GetLastError());
+                continue;
+            }
+
+            /* FIXME: Use new_cert->hCertStore once cert ref count bug is fixed. */
+            new_store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0, CERT_STORE_CREATE_NEW_FLAG, NULL);
+            CertAddCertificateContextToStore(new_store, new_cert, CERT_STORE_ADD_NEW, NULL);
+            issuer = CertFindCertificateInStore(new_store, cert->dwCertEncodingType, 0, type, para, NULL);
+            CertFreeCertificateContext(new_cert);
+            CertCloseStore(new_store, 0);
+            if(issuer)
+            {
+                TRACE("Found downloaded issuer %p\n", issuer);
+                break;
+            }
+        }
+    }
+
+    HeapFree(GetProcessHeap(), 0, urls);
+    return issuer;
+}
+
+static PCCERT_CONTEXT CRYPT_GetIssuer(const CertificateChainEngine *engine,
+        HCERTSTORE store, PCCERT_CONTEXT subject, PCCERT_CONTEXT prevIssuer,
+        DWORD flags, DWORD *infoStatus)
 {
     PCCERT_CONTEXT issuer = NULL;
     PCERT_EXTENSION ext;
@@ -1993,9 +2086,8 @@ static PCCERT_CONTEXT CRYPT_GetIssuer(HCERTSTORE store, PCCERT_CONTEXT subject,
                  sizeof(CERT_NAME_BLOB));
                 memcpy(&id.u.IssuerSerialNumber.SerialNumber,
                  &info->CertSerialNumber, sizeof(CRYPT_INTEGER_BLOB));
-                issuer = CertFindCertificateInStore(store,
-                 subject->dwCertEncodingType, 0, CERT_FIND_CERT_ID, &id,
-                 prevIssuer);
+
+                issuer = CRYPT_FindIssuer(engine, subject, store, CERT_FIND_CERT_ID, &id, flags, prevIssuer);
                 if (issuer)
                 {
                     TRACE_(chain)("issuer found by issuer/serial number\n");
@@ -2005,10 +2097,9 @@ static PCCERT_CONTEXT CRYPT_GetIssuer(HCERTSTORE store, PCCERT_CONTEXT subject,
             else if (info->KeyId.cbData)
             {
                 id.dwIdChoice = CERT_ID_KEY_IDENTIFIER;
+
                 memcpy(&id.u.KeyId, &info->KeyId, sizeof(CRYPT_HASH_BLOB));
-                issuer = CertFindCertificateInStore(store,
-                 subject->dwCertEncodingType, 0, CERT_FIND_CERT_ID, &id,
-                 prevIssuer);
+                issuer = CRYPT_FindIssuer(engine, subject, store, CERT_FIND_CERT_ID, &id, flags, prevIssuer);
                 if (issuer)
                 {
                     TRACE_(chain)("issuer found by key id\n");
@@ -2052,9 +2143,8 @@ static PCCERT_CONTEXT CRYPT_GetIssuer(HCERTSTORE store, PCCERT_CONTEXT subject,
                     memcpy(&id.u.IssuerSerialNumber.SerialNumber,
                      &info->AuthorityCertSerialNumber,
                      sizeof(CRYPT_INTEGER_BLOB));
-                    issuer = CertFindCertificateInStore(store,
-                     subject->dwCertEncodingType, 0, CERT_FIND_CERT_ID, &id,
-                     prevIssuer);
+
+                    issuer = CRYPT_FindIssuer(engine, subject, store, CERT_FIND_CERT_ID, &id, flags, prevIssuer);
                     if (issuer)
                     {
                         TRACE_(chain)("issuer found by directory name\n");
@@ -2068,9 +2158,7 @@ static PCCERT_CONTEXT CRYPT_GetIssuer(HCERTSTORE store, PCCERT_CONTEXT subject,
             {
                 id.dwIdChoice = CERT_ID_KEY_IDENTIFIER;
                 memcpy(&id.u.KeyId, &info->KeyId, sizeof(CRYPT_HASH_BLOB));
-                issuer = CertFindCertificateInStore(store,
-                 subject->dwCertEncodingType, 0, CERT_FIND_CERT_ID, &id,
-                 prevIssuer);
+                issuer = CRYPT_FindIssuer(engine, subject, store, CERT_FIND_CERT_ID, &id, flags, prevIssuer);
                 if (issuer)
                 {
                     TRACE_(chain)("issuer found by key id\n");
@@ -2082,9 +2170,8 @@ static PCCERT_CONTEXT CRYPT_GetIssuer(HCERTSTORE store, PCCERT_CONTEXT subject,
     }
     else
     {
-        issuer = CertFindCertificateInStore(store,
-         subject->dwCertEncodingType, 0, CERT_FIND_SUBJECT_NAME,
-         &subject->pCertInfo->Issuer, prevIssuer);
+        issuer = CRYPT_FindIssuer(engine, subject, store, CERT_FIND_SUBJECT_NAME,
+         &subject->pCertInfo->Issuer, flags, prevIssuer);
         TRACE_(chain)("issuer found by name\n");
         *infoStatus = CERT_TRUST_HAS_NAME_MATCH_ISSUER;
     }
@@ -2095,7 +2182,7 @@ static PCCERT_CONTEXT CRYPT_GetIssuer(HCERTSTORE store, PCCERT_CONTEXT subject,
  * until reaching a self-signed cert, or until no issuer can be found.
  */
 static BOOL CRYPT_BuildSimpleChain(const CertificateChainEngine *engine,
- HCERTSTORE world, PCERT_SIMPLE_CHAIN chain)
+ HCERTSTORE world, DWORD flags, PCERT_SIMPLE_CHAIN chain)
 {
     BOOL ret = TRUE;
     PCCERT_CONTEXT cert = chain->rgpElement[chain->cElement - 1]->pCertContext;
@@ -2103,7 +2190,7 @@ static BOOL CRYPT_BuildSimpleChain(const CertificateChainEngine *engine,
     while (ret && !CRYPT_IsSimpleChainCyclic(chain) &&
      !CRYPT_IsCertificateSelfSigned(cert))
     {
-        PCCERT_CONTEXT issuer = CRYPT_GetIssuer(world, cert, NULL,
+        PCCERT_CONTEXT issuer = CRYPT_GetIssuer(engine, world, cert, NULL, flags,
          &chain->rgpElement[chain->cElement - 1]->TrustStatus.dwInfoStatus);
 
         if (issuer)
@@ -2133,8 +2220,8 @@ static LPCSTR debugstr_filetime(LPFILETIME pTime)
     return wine_dbg_sprintf("%p (%s)", pTime, filetime_to_str(pTime));
 }
 
-static BOOL CRYPT_GetSimpleChainForCert(PCertificateChainEngine engine,
- HCERTSTORE world, PCCERT_CONTEXT cert, LPFILETIME pTime,
+static BOOL CRYPT_GetSimpleChainForCert(CertificateChainEngine *engine,
+ HCERTSTORE world, PCCERT_CONTEXT cert, LPFILETIME pTime, DWORD flags,
  PCERT_SIMPLE_CHAIN *ppChain)
 {
     BOOL ret = FALSE;
@@ -2150,7 +2237,7 @@ static BOOL CRYPT_GetSimpleChainForCert(PCertificateChainEngine engine,
         ret = CRYPT_AddCertToSimpleChain(engine, chain, cert, 0);
         if (ret)
         {
-            ret = CRYPT_BuildSimpleChain(engine, world, chain);
+            ret = CRYPT_BuildSimpleChain(engine, world, flags, chain);
             if (ret)
                 CRYPT_CheckSimpleChain(engine, chain, pTime);
         }
@@ -2164,11 +2251,10 @@ static BOOL CRYPT_GetSimpleChainForCert(PCertificateChainEngine engine,
     return ret;
 }
 
-static BOOL CRYPT_BuildCandidateChainFromCert(HCERTCHAINENGINE hChainEngine,
- PCCERT_CONTEXT cert, LPFILETIME pTime, HCERTSTORE hAdditionalStore,
PCertificateChain *ppChain)
+static BOOL CRYPT_BuildCandidateChainFromCert(CertificateChainEngine *engine,
+ PCCERT_CONTEXT cert, LPFILETIME pTime, HCERTSTORE hAdditionalStore, DWORD flags,
CertificateChain **ppChain)
 {
-    PCertificateChainEngine engine = (PCertificateChainEngine)hChainEngine;
     PCERT_SIMPLE_CHAIN simpleChain = NULL;
     HCERTSTORE world;
     BOOL ret;
@@ -2181,10 +2267,9 @@ static BOOL CRYPT_BuildCandidateChainFromCert(HCERTCHAINENGINE hChainEngine,
     /* FIXME: only simple chains are supported for now, as CTLs aren't
      * supported yet.
      */
-    if ((ret = CRYPT_GetSimpleChainForCert(engine, world, cert, pTime,
-     &simpleChain)))
+    if ((ret = CRYPT_GetSimpleChainForCert(engine, world, cert, pTime, flags, &simpleChain)))
     {
-        PCertificateChain chain = CryptMemAlloc(sizeof(CertificateChain));
+        CertificateChain *chain = CryptMemAlloc(sizeof(CertificateChain));
 
         if (chain)
         {
@@ -2263,7 +2348,7 @@ static PCERT_SIMPLE_CHAIN CRYPT_CopySimpleChainToElement(
     return copy;
 }
 
-static void CRYPT_FreeLowerQualityChains(PCertificateChain chain)
+static void CRYPT_FreeLowerQualityChains(CertificateChain *chain)
 {
     DWORD i;
 
@@ -2274,7 +2359,7 @@ static void CRYPT_FreeLowerQualityChains(PCertificateChain chain)
     chain->context.rgpLowerQualityChainContext = NULL;
 }
 
-static void CRYPT_FreeChainContext(PCertificateChain chain)
+static void CRYPT_FreeChainContext(CertificateChain *chain)
 {
     DWORD i;
 
@@ -2289,10 +2374,10 @@ static void CRYPT_FreeChainContext(PCertificateChain chain)
 /* Makes and returns a copy of chain, up to and including element iElement of
  * simple chain iChain.
  */
-static PCertificateChain CRYPT_CopyChainToElement(PCertificateChain chain,
+static CertificateChain *CRYPT_CopyChainToElement(CertificateChain *chain,
  DWORD iChain, DWORD iElement)
 {
-    PCertificateChain copy = CryptMemAlloc(sizeof(CertificateChain));
+    CertificateChain *copy = CryptMemAlloc(sizeof(CertificateChain));
 
     if (copy)
     {
@@ -2354,21 +2439,20 @@ static PCertificateChain CRYPT_CopyChainToElement(PCertificateChain chain,
     return copy;
 }
 
-static PCertificateChain CRYPT_BuildAlternateContextFromChain(
HCERTCHAINENGINE hChainEngine, LPFILETIME pTime, HCERTSTORE hAdditionalStore,
PCertificateChain chain)
+static CertificateChain *CRYPT_BuildAlternateContextFromChain(
CertificateChainEngine *engine, LPFILETIME pTime, HCERTSTORE hAdditionalStore,
DWORD flags, CertificateChain *chain)
 {
-    PCertificateChainEngine engine = (PCertificateChainEngine)hChainEngine;
-    PCertificateChain alternate;
+    CertificateChain *alternate;
 
-    TRACE("(%p, %s, %p, %p)\n", hChainEngine, debugstr_filetime(pTime),
+    TRACE("(%p, %s, %p, %p)\n", engine, debugstr_filetime(pTime),
      hAdditionalStore, chain);
 
     /* Always start with the last "lower quality" chain to ensure a consistent
      * order of alternate creation:
      */
     if (chain->context.cLowerQualityChainContext)
-        chain = (PCertificateChain)chain->context.rgpLowerQualityChainContext[
+        chain = (CertificateChain*)chain->context.rgpLowerQualityChainContext[
          chain->context.cLowerQualityChainContext - 1];
     /* A chain with only one element can't have any alternates */
     if (chain->context.cChain <= 1 && chain->context.rgpChain[0]->cElement <= 1)
@@ -2388,8 +2472,8 @@ static PCertificateChain CRYPT_BuildAlternateContextFromChain(
                 PCCERT_CONTEXT prevIssuer = CertDuplicateCertificateContext(
                  chain->context.rgpChain[i]->rgpElement[j + 1]->pCertContext);
 
-                alternateIssuer = CRYPT_GetIssuer(prevIssuer->hCertStore,
-                 subject, prevIssuer, &infoStatus);
+                alternateIssuer = CRYPT_GetIssuer(engine, prevIssuer->hCertStore,
+                 subject, prevIssuer, flags, &infoStatus);
             }
         if (alternateIssuer)
         {
@@ -2408,7 +2492,7 @@ static PCertificateChain CRYPT_BuildAlternateContextFromChain(
                 if (ret)
                 {
                     ret = CRYPT_BuildSimpleChain(engine, alternate->world,
-                     alternate->context.rgpChain[i]);
+                     flags, alternate->context.rgpChain[i]);
                     if (ret)
                         CRYPT_CheckSimpleChain(engine,
                          alternate->context.rgpChain[i], pTime);
@@ -2467,8 +2551,8 @@ static DWORD CRYPT_ChainQuality(const CertificateChain *chain)
  * alternate chains.  Returns the highest quality chain, with all other
  * chains as lower quality chains of it.
  */
-static PCertificateChain CRYPT_ChooseHighestQualityChain(
PCertificateChain chain)
+static CertificateChain *CRYPT_ChooseHighestQualityChain(
CertificateChain *chain)
 {
     DWORD i;
 
@@ -2480,8 +2564,8 @@ static PCertificateChain CRYPT_ChooseHighestQualityChain(
      */
     for (i = 0; i < chain->context.cLowerQualityChainContext; i++)
     {
-        PCertificateChain alternate =
-         (PCertificateChain)chain->context.rgpLowerQualityChainContext[i];
+        CertificateChain *alternate =
+         (CertificateChain*)chain->context.rgpLowerQualityChainContext[i];
 
         if (CRYPT_ChainQuality(alternate) > CRYPT_ChainQuality(chain))
         {
@@ -2499,7 +2583,7 @@ static PCertificateChain CRYPT_ChooseHighestQualityChain(
     return chain;
 }
 
-static BOOL CRYPT_AddAlternateChainToChain(PCertificateChain chain,
+static BOOL CRYPT_AddAlternateChainToChain(CertificateChain *chain,
  const CertificateChain *alternate)
 {
     BOOL ret;
@@ -2543,7 +2627,7 @@ static PCERT_CHAIN_ELEMENT CRYPT_FindIthElementInChain(
 typedef struct _CERT_CHAIN_PARA_NO_EXTRA_FIELDS {
     DWORD            cbSize;
     CERT_USAGE_MATCH RequestedUsage;
-} CERT_CHAIN_PARA_NO_EXTRA_FIELDS, *PCERT_CHAIN_PARA_NO_EXTRA_FIELDS;
+} CERT_CHAIN_PARA_NO_EXTRA_FIELDS;
 
 static void CRYPT_VerifyChainRevocation(PCERT_CHAIN_CONTEXT chain,
  LPFILETIME pTime, HCERTSTORE hAdditionalStore,
@@ -2792,13 +2876,18 @@ BOOL WINAPI CertGetCertificateChain(HCERTCHAINENGINE hChainEngine,
  PCERT_CHAIN_PARA pChainPara, DWORD dwFlags, LPVOID pvReserved,
  PCCERT_CHAIN_CONTEXT* ppChainContext)
 {
+    CertificateChainEngine *engine;
     BOOL ret;
-    PCertificateChain chain = NULL;
+    CertificateChain *chain = NULL;
 
     TRACE("(%p, %p, %s, %p, %p, %08x, %p, %p)\n", hChainEngine, pCertContext,
      debugstr_filetime(pTime), hAdditionalStore, pChainPara, dwFlags,
      pvReserved, ppChainContext);
 
+    engine = get_chain_engine(hChainEngine, TRUE);
+    if (!engine)
+        return FALSE;
+
     if (ppChainContext)
         *ppChainContext = NULL;
     if (!pChainPara)
@@ -2812,21 +2901,19 @@ BOOL WINAPI CertGetCertificateChain(HCERTCHAINENGINE hChainEngine,
         return FALSE;
     }
 
-    if (!hChainEngine)
-        hChainEngine = CRYPT_GetDefaultChainEngine();
     if (TRACE_ON(chain))
         dump_chain_para(pChainPara);
     /* FIXME: what about HCCE_LOCAL_MACHINE? */
-    ret = CRYPT_BuildCandidateChainFromCert(hChainEngine, pCertContext, pTime,
-     hAdditionalStore, &chain);
+    ret = CRYPT_BuildCandidateChainFromCert(engine, pCertContext, pTime,
+     hAdditionalStore, dwFlags, &chain);
     if (ret)
     {
-        PCertificateChain alternate = NULL;
+        CertificateChain *alternate = NULL;
         PCERT_CHAIN_CONTEXT pChain;
 
         do {
-            alternate = CRYPT_BuildAlternateContextFromChain(hChainEngine,
-             pTime, hAdditionalStore, chain);
+            alternate = CRYPT_BuildAlternateContextFromChain(engine,
+             pTime, hAdditionalStore, dwFlags, chain);
 
             /* Alternate contexts are added as "lower quality" contexts of
              * chain, to avoid loops in alternate chain creation.
@@ -2856,7 +2943,7 @@ BOOL WINAPI CertGetCertificateChain(HCERTCHAINENGINE hChainEngine,
 PCCERT_CHAIN_CONTEXT WINAPI CertDuplicateCertificateChain(
  PCCERT_CHAIN_CONTEXT pChainContext)
 {
-    PCertificateChain chain = (PCertificateChain)pChainContext;
+    CertificateChain *chain = (CertificateChain*)pChainContext;
 
     TRACE("(%p)\n", pChainContext);
 
@@ -2867,7 +2954,7 @@ PCCERT_CHAIN_CONTEXT WINAPI CertDuplicateCertificateChain(
 
 VOID WINAPI CertFreeCertificateChain(PCCERT_CHAIN_CONTEXT pChainContext)
 {
-    PCertificateChain chain = (PCertificateChain)pChainContext;
+    CertificateChain *chain = (CertificateChain*)pChainContext;
 
     TRACE("(%p)\n", pChainContext);
 
index 192cab6..366bdac 100644 (file)
@@ -22,92 +22,106 @@ WINE_DEFAULT_DEBUG_CHANNEL(crypt);
 
 typedef struct _WINE_STORE_LIST_ENTRY
 {
-    PWINECRYPT_CERTSTORE store;
+    WINECRYPT_CERTSTORE *store;
     DWORD                dwUpdateFlags;
     DWORD                dwPriority;
     struct list          entry;
-} WINE_STORE_LIST_ENTRY, *PWINE_STORE_LIST_ENTRY;
+} WINE_STORE_LIST_ENTRY;
 
 typedef struct _WINE_COLLECTIONSTORE
 {
     WINECRYPT_CERTSTORE hdr;
     CRITICAL_SECTION    cs;
     struct list         stores;
-} WINE_COLLECTIONSTORE, *PWINE_COLLECTIONSTORE;
+} WINE_COLLECTIONSTORE;
 
-static void WINAPI CRYPT_CollectionCloseStore(HCERTSTORE store, DWORD dwFlags)
+static void Collection_addref(WINECRYPT_CERTSTORE *store)
 {
-    PWINE_COLLECTIONSTORE cs = store;
-    PWINE_STORE_LIST_ENTRY entry, next;
+    LONG ref = InterlockedIncrement(&store->ref);
+    TRACE("ref = %d\n", ref);
+}
+
+static DWORD Collection_release(WINECRYPT_CERTSTORE *store, DWORD flags)
+{
+    WINE_COLLECTIONSTORE *cs = (WINE_COLLECTIONSTORE*)store;
+    WINE_STORE_LIST_ENTRY *entry, *next;
+    LONG ref;
+
+    if(flags)
+        FIXME("Unimplemented flags %x\n", flags);
 
-    TRACE("(%p, %08x)\n", store, dwFlags);
+    ref = InterlockedDecrement(&cs->hdr.ref);
+    TRACE("(%p) ref=%d\n", store, ref);
+    if(ref)
+        return ERROR_SUCCESS;
 
-    LIST_FOR_EACH_ENTRY_SAFE(entry, next, &cs->stores, WINE_STORE_LIST_ENTRY,
-     entry)
+    LIST_FOR_EACH_ENTRY_SAFE(entry, next, &cs->stores, WINE_STORE_LIST_ENTRY, entry)
     {
         TRACE("closing %p\n", entry);
-        CertCloseStore(entry->store, dwFlags);
+        entry->store->vtbl->release(entry->store, flags);
         CryptMemFree(entry);
     }
     cs->cs.DebugInfo->Spare[0] = 0;
     DeleteCriticalSection(&cs->cs);
     CRYPT_FreeStore(store);
+    return ERROR_SUCCESS;
 }
 
-static void *CRYPT_CollectionCreateContextFromChild(PWINE_COLLECTIONSTORE store,
- PWINE_STORE_LIST_ENTRY storeEntry, void *child, size_t contextSize,
- BOOL addRef)
+static void Collection_releaseContext(WINECRYPT_CERTSTORE *store, context_t *context)
 {
-    void *ret = Context_CreateLinkContext(contextSize, child,
-     sizeof(PWINE_STORE_LIST_ENTRY), addRef);
+    /* We don't cache context links, so just free them. */
+    Context_Free(context);
+}
+
+static context_t *CRYPT_CollectionCreateContextFromChild(WINE_COLLECTIONSTORE *store,
+ WINE_STORE_LIST_ENTRY *storeEntry, context_t *child)
+{
+    context_t *ret;
 
-    if (ret)
-        *(PWINE_STORE_LIST_ENTRY *)Context_GetExtra(ret, contextSize)
-         = storeEntry;
+    ret = child->vtbl->clone(child, &store->hdr, TRUE);
+    if (!ret)
+        return NULL;
 
+    ret->u.ptr = storeEntry;
     return ret;
 }
 
-static BOOL CRYPT_CollectionAddContext(PWINE_COLLECTIONSTORE store,
- unsigned int contextFuncsOffset, void *context, void *toReplace, unsigned int contextSize,
void **pChildContext)
+static BOOL CRYPT_CollectionAddContext(WINE_COLLECTIONSTORE *store,
+ unsigned int contextFuncsOffset, context_t *context, context_t *toReplace,
context_t **pChildContext)
 {
     BOOL ret;
-    void *childContext = NULL;
-    PWINE_STORE_LIST_ENTRY storeEntry = NULL;
+    context_t *childContext = NULL;
+    WINE_STORE_LIST_ENTRY *storeEntry = NULL;
 
-    TRACE("(%p, %d, %p, %p, %d)\n", store, contextFuncsOffset, context,
-     toReplace, contextSize);
+    TRACE("(%p, %d, %p, %p)\n", store, contextFuncsOffset, context, toReplace);
 
     ret = FALSE;
     if (toReplace)
     {
-        void *existingLinked = Context_GetLinkedContext(toReplace, contextSize);
-        PCONTEXT_FUNCS contextFuncs;
+        context_t *existingLinked = toReplace->linked;
+        CONTEXT_FUNCS *contextFuncs;
 
-        storeEntry = *(PWINE_STORE_LIST_ENTRY *)Context_GetExtra(toReplace,
-         contextSize);
-        contextFuncs = (PCONTEXT_FUNCS)((LPBYTE)storeEntry->store +
+        storeEntry = toReplace->u.ptr;
+        contextFuncs = (CONTEXT_FUNCS*)((LPBYTE)storeEntry->store->vtbl +
          contextFuncsOffset);
         ret = contextFuncs->addContext(storeEntry->store, context,
-         existingLinked, (const void **)&childContext);
+         existingLinked, &childContext, TRUE);
     }
     else
     {
-        PWINE_STORE_LIST_ENTRY entry, next;
+        WINE_STORE_LIST_ENTRY *entry, *next;
 
         EnterCriticalSection(&store->cs);
-        LIST_FOR_EACH_ENTRY_SAFE(entry, next, &store->stores,
-         WINE_STORE_LIST_ENTRY, entry)
+        LIST_FOR_EACH_ENTRY_SAFE(entry, next, &store->stores, WINE_STORE_LIST_ENTRY, entry)
         {
             if (entry->dwUpdateFlags & CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG)
             {
-                PCONTEXT_FUNCS contextFuncs = (PCONTEXT_FUNCS)(
-                 (LPBYTE)entry->store + contextFuncsOffset);
+                CONTEXT_FUNCS *contextFuncs = (CONTEXT_FUNCS*)(
+                 (LPBYTE)entry->store->vtbl + contextFuncsOffset);
 
                 storeEntry = entry;
-                ret = contextFuncs->addContext(entry->store, context, NULL,
-                 (const void **)&childContext);
+                ret = contextFuncs->addContext(entry->store, context, NULL, &childContext, TRUE);
                 break;
             }
         }
@@ -128,31 +142,34 @@ static BOOL CRYPT_CollectionAddContext(PWINE_COLLECTIONSTORE store,
  * Returns NULL if the collection contains no more items or on error.
  * Assumes the collection store's lock is held.
  */
-static void *CRYPT_CollectionAdvanceEnum(PWINE_COLLECTIONSTORE store,
PWINE_STORE_LIST_ENTRY storeEntry, const CONTEXT_FUNCS *contextFuncs,
PCWINE_CONTEXT_INTERFACE contextInterface, void *pPrev, size_t contextSize)
+static context_t *CRYPT_CollectionAdvanceEnum(WINE_COLLECTIONSTORE *store,
WINE_STORE_LIST_ENTRY *storeEntry, const CONTEXT_FUNCS *contextFuncs,
context_t *prev)
 {
-    void *ret, *child;
+    context_t *child, *ret;
     struct list *storeNext = list_next(&store->stores, &storeEntry->entry);
 
-    TRACE("(%p, %p, %p)\n", store, storeEntry, pPrev);
+    TRACE("(%p, %p, %p)\n", store, storeEntry, prev);
 
-    if (pPrev)
+    if (prev)
     {
         /* Ref-counting funny business: "duplicate" (addref) the child, because
          * the free(pPrev) below can cause the ref count to become negative.
          */
-        child = Context_GetLinkedContext(pPrev, contextSize);
-        contextInterface->duplicate(child);
+        child = prev->linked;
+        Context_AddRef(child);
         child = contextFuncs->enumContext(storeEntry->store, child);
-        contextInterface->free(pPrev);
-        pPrev = NULL;
+        Context_Release(prev);
+        prev = NULL;
     }
     else
+    {
         child = contextFuncs->enumContext(storeEntry->store, NULL);
-    if (child)
-        ret = CRYPT_CollectionCreateContextFromChild(store, storeEntry, child,
-         contextSize, FALSE);
+    }
+    if (child) {
+        ret = CRYPT_CollectionCreateContextFromChild(store, storeEntry, child);
+        Context_Release(child);
+    }
     else
     {
         if (storeNext)
@@ -160,14 +177,14 @@ static void *CRYPT_CollectionAdvanceEnum(PWINE_COLLECTIONSTORE store,
             /* We always want the same function pointers (from certs, crls)
              * in the next store, so use the same offset into the next store.
              */
-            size_t offset = (const BYTE *)contextFuncs - (LPBYTE)storeEntry->store;
-            PWINE_STORE_LIST_ENTRY storeNextEntry =
+            size_t offset = (const BYTE *)contextFuncs - (LPBYTE)storeEntry->store->vtbl;
+            WINE_STORE_LIST_ENTRY *storeNextEntry =
              LIST_ENTRY(storeNext, WINE_STORE_LIST_ENTRY, entry);
-            PCONTEXT_FUNCS storeNextContexts =
-             (PCONTEXT_FUNCS)((LPBYTE)storeNextEntry->store + offset);
+            CONTEXT_FUNCS *storeNextContexts =
+             (CONTEXT_FUNCS*)((LPBYTE)storeNextEntry->store->vtbl + offset);
 
             ret = CRYPT_CollectionAdvanceEnum(store, storeNextEntry,
-             storeNextContexts, contextInterface, NULL, contextSize);
+             storeNextContexts, NULL);
         }
         else
         {
@@ -179,59 +196,52 @@ static void *CRYPT_CollectionAdvanceEnum(PWINE_COLLECTIONSTORE store,
     return ret;
 }
 
-static BOOL CRYPT_CollectionAddCert(PWINECRYPT_CERTSTORE store, void *cert,
void *toReplace, const void **ppStoreContext)
+static BOOL Collection_addCert(WINECRYPT_CERTSTORE *store, context_t *cert,
context_t *toReplace, context_t **ppStoreContext, BOOL use_link)
 {
     BOOL ret;
-    void *childContext = NULL;
-    PWINE_COLLECTIONSTORE cs = (PWINE_COLLECTIONSTORE)store;
+    context_t *childContext = NULL;
+    WINE_COLLECTIONSTORE *cs = (WINE_COLLECTIONSTORE*)store;
 
-    ret = CRYPT_CollectionAddContext(cs, offsetof(WINECRYPT_CERTSTORE, certs),
-     cert, toReplace, sizeof(CERT_CONTEXT), &childContext);
+    ret = CRYPT_CollectionAddContext(cs, offsetof(store_vtbl_t, certs),
+     cert, toReplace, &childContext);
     if (ppStoreContext && childContext)
     {
-        PWINE_STORE_LIST_ENTRY storeEntry = *(PWINE_STORE_LIST_ENTRY *)
-         Context_GetExtra(childContext, sizeof(CERT_CONTEXT));
-        PCERT_CONTEXT context =
-         CRYPT_CollectionCreateContextFromChild(cs, storeEntry, childContext,
-         sizeof(CERT_CONTEXT), TRUE);
-
-        if (context)
-            context->hCertStore = store;
-        *ppStoreContext = context;
+        WINE_STORE_LIST_ENTRY *storeEntry = childContext->u.ptr;
+        cert_t *context = (cert_t*)CRYPT_CollectionCreateContextFromChild(cs, storeEntry,
+         childContext);
+
+        *ppStoreContext = &context->base;
     }
-    CertFreeCertificateContext(childContext);
+    if (childContext)
+        Context_Release(childContext);
     return ret;
 }
 
-static void *CRYPT_CollectionEnumCert(PWINECRYPT_CERTSTORE store, void *pPrev)
+static context_t *Collection_enumCert(WINECRYPT_CERTSTORE *store, context_t *prev)
 {
-    PWINE_COLLECTIONSTORE cs = (PWINE_COLLECTIONSTORE)store;
-    void *ret;
+    WINE_COLLECTIONSTORE *cs = (WINE_COLLECTIONSTORE*)store;
+    context_t *ret;
 
-    TRACE("(%p, %p)\n", store, pPrev);
+    TRACE("(%p, %p)\n", store, prev);
 
     EnterCriticalSection(&cs->cs);
-    if (pPrev)
+    if (prev)
     {
-        PWINE_STORE_LIST_ENTRY storeEntry =
-         *(PWINE_STORE_LIST_ENTRY *)Context_GetExtra(pPrev,
-         sizeof(CERT_CONTEXT));
+        WINE_STORE_LIST_ENTRY *storeEntry = prev->u.ptr;
 
         ret = CRYPT_CollectionAdvanceEnum(cs, storeEntry,
-         &storeEntry->store->certs, pCertInterface, pPrev,
-         sizeof(CERT_CONTEXT));
+         &storeEntry->store->vtbl->certs, prev);
     }
     else
     {
         if (!list_empty(&cs->stores))
         {
-            PWINE_STORE_LIST_ENTRY storeEntry = LIST_ENTRY(cs->stores.next,
+            WINE_STORE_LIST_ENTRY *storeEntry = LIST_ENTRY(cs->stores.next,
              WINE_STORE_LIST_ENTRY, entry);
 
             ret = CRYPT_CollectionAdvanceEnum(cs, storeEntry,
-             &storeEntry->store->certs, pCertInterface, NULL,
-             sizeof(CERT_CONTEXT));
+             &storeEntry->store->vtbl->certs, NULL);
         }
         else
         {
@@ -240,84 +250,67 @@ static void *CRYPT_CollectionEnumCert(PWINECRYPT_CERTSTORE store, void *pPrev)
         }
     }
     LeaveCriticalSection(&cs->cs);
-    if (ret)
-        ((PCERT_CONTEXT)ret)->hCertStore = store;
     TRACE("returning %p\n", ret);
     return ret;
 }
 
-static BOOL CRYPT_CollectionDeleteCert(PWINECRYPT_CERTSTORE store,
- void *pCertContext)
+static BOOL Collection_deleteCert(WINECRYPT_CERTSTORE *store, context_t *context)
 {
-    BOOL ret;
-    PCCERT_CONTEXT linked;
-
-    TRACE("(%p, %p)\n", store, pCertContext);
-
-    /* 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;
+    cert_t *cert = (cert_t*)context;
+    cert_t *linked;
+
+    TRACE("(%p, %p)\n", store, cert);
+
+    linked = (cert_t*)context->linked;
+    return CertDeleteCertificateFromStore(&linked->ctx);
 }
 
-static BOOL CRYPT_CollectionAddCRL(PWINECRYPT_CERTSTORE store, void *crl,
void *toReplace, const void **ppStoreContext)
+static BOOL Collection_addCRL(WINECRYPT_CERTSTORE *store, context_t *crl,
context_t *toReplace, context_t **ppStoreContext, BOOL use_link)
 {
     BOOL ret;
-    void *childContext = NULL;
-    PWINE_COLLECTIONSTORE cs = (PWINE_COLLECTIONSTORE)store;
+    context_t *childContext = NULL;
+    WINE_COLLECTIONSTORE *cs = (WINE_COLLECTIONSTORE*)store;
 
-    ret = CRYPT_CollectionAddContext(cs, offsetof(WINECRYPT_CERTSTORE, crls),
-     crl, toReplace, sizeof(CRL_CONTEXT), &childContext);
+    ret = CRYPT_CollectionAddContext(cs, offsetof(store_vtbl_t, crls),
+     crl, toReplace, &childContext);
     if (ppStoreContext && childContext)
     {
-        PWINE_STORE_LIST_ENTRY storeEntry = *(PWINE_STORE_LIST_ENTRY *)
-         Context_GetExtra(childContext, sizeof(CRL_CONTEXT));
-        PCRL_CONTEXT context =
-         CRYPT_CollectionCreateContextFromChild(cs, storeEntry, childContext,
-         sizeof(CRL_CONTEXT), TRUE);
-
-        if (context)
-            context->hCertStore = store;
-        *ppStoreContext = context;
+        WINE_STORE_LIST_ENTRY *storeEntry = childContext->u.ptr;
+        crl_t *context = (crl_t*)CRYPT_CollectionCreateContextFromChild(cs, storeEntry,
+         childContext);
+
+        *ppStoreContext = &context->base;
     }
-    CertFreeCRLContext(childContext);
+    if (childContext)
+        Context_Release(childContext);
     return ret;
 }
 
-static void *CRYPT_CollectionEnumCRL(PWINECRYPT_CERTSTORE store, void *pPrev)
+static context_t *Collection_enumCRL(WINECRYPT_CERTSTORE *store, context_t *prev)
 {
-    PWINE_COLLECTIONSTORE cs = (PWINE_COLLECTIONSTORE)store;
-    void *ret;
+    WINE_COLLECTIONSTORE *cs = (WINE_COLLECTIONSTORE*)store;
+    context_t *ret;
 
-    TRACE("(%p, %p)\n", store, pPrev);
+    TRACE("(%p, %p)\n", store, prev);
 
     EnterCriticalSection(&cs->cs);
-    if (pPrev)
+    if (prev)
     {
-        PWINE_STORE_LIST_ENTRY storeEntry =
-         *(PWINE_STORE_LIST_ENTRY *)Context_GetExtra(pPrev,
-         sizeof(CRL_CONTEXT));
+        WINE_STORE_LIST_ENTRY *storeEntry = prev->u.ptr;
 
         ret = CRYPT_CollectionAdvanceEnum(cs, storeEntry,
-         &storeEntry->store->crls, pCRLInterface, pPrev, sizeof(CRL_CONTEXT));
+         &storeEntry->store->vtbl->crls, prev);
     }
     else
     {
         if (!list_empty(&cs->stores))
         {
-            PWINE_STORE_LIST_ENTRY storeEntry = LIST_ENTRY(cs->stores.next,
+            WINE_STORE_LIST_ENTRY *storeEntry = LIST_ENTRY(cs->stores.next,
              WINE_STORE_LIST_ENTRY, entry);
 
             ret = CRYPT_CollectionAdvanceEnum(cs, storeEntry,
-             &storeEntry->store->crls, pCRLInterface, NULL,
-             sizeof(CRL_CONTEXT));
+             &storeEntry->store->vtbl->crls, NULL);
         }
         else
         {
@@ -326,83 +319,66 @@ static void *CRYPT_CollectionEnumCRL(PWINECRYPT_CERTSTORE store, void *pPrev)
         }
     }
     LeaveCriticalSection(&cs->cs);
-    if (ret)
-        ((PCRL_CONTEXT)ret)->hCertStore = store;
     TRACE("returning %p\n", ret);
     return ret;
 }
 
-static BOOL CRYPT_CollectionDeleteCRL(PWINECRYPT_CERTSTORE store,
- void *pCrlContext)
+static BOOL Collection_deleteCRL(WINECRYPT_CERTSTORE *store, context_t *context)
 {
-    BOOL ret;
-    PCCRL_CONTEXT linked;
-
-    TRACE("(%p, %p)\n", store, pCrlContext);
-
-    /* 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;
+    crl_t *crl = (crl_t*)context, *linked;
+
+    TRACE("(%p, %p)\n", store, crl);
+
+    linked = (crl_t*)context->linked;
+    return CertDeleteCRLFromStore(&linked->ctx);
 }
 
-static BOOL CRYPT_CollectionAddCTL(PWINECRYPT_CERTSTORE store, void *ctl,
void *toReplace, const void **ppStoreContext)
+static BOOL Collection_addCTL(WINECRYPT_CERTSTORE *store, context_t *ctl,
context_t *toReplace, context_t **ppStoreContext, BOOL use_link)
 {
     BOOL ret;
-    void *childContext = NULL;
-    PWINE_COLLECTIONSTORE cs = (PWINE_COLLECTIONSTORE)store;
+    context_t *childContext = NULL;
+    WINE_COLLECTIONSTORE *cs = (WINE_COLLECTIONSTORE*)store;
 
-    ret = CRYPT_CollectionAddContext(cs, offsetof(WINECRYPT_CERTSTORE, ctls),
-     ctl, toReplace, sizeof(CTL_CONTEXT), &childContext);
+    ret = CRYPT_CollectionAddContext(cs, offsetof(store_vtbl_t, ctls),
+     ctl, toReplace, &childContext);
     if (ppStoreContext && childContext)
     {
-        PWINE_STORE_LIST_ENTRY storeEntry = *(PWINE_STORE_LIST_ENTRY *)
-         Context_GetExtra(childContext, sizeof(CTL_CONTEXT));
-        PCTL_CONTEXT context =
-         CRYPT_CollectionCreateContextFromChild(cs, storeEntry, childContext,
-         sizeof(CTL_CONTEXT), TRUE);
-
-        if (context)
-            context->hCertStore = store;
-        *ppStoreContext = context;
+        WINE_STORE_LIST_ENTRY *storeEntry = childContext->u.ptr;
+        ctl_t *context = (ctl_t*)CRYPT_CollectionCreateContextFromChild(cs, storeEntry,
+         childContext);
+
+        *ppStoreContext = &context->base;
     }
-    CertFreeCTLContext(childContext);
+    if (childContext)
+        Context_Release(childContext);
     return ret;
 }
 
-static void *CRYPT_CollectionEnumCTL(PWINECRYPT_CERTSTORE store, void *pPrev)
+static context_t *Collection_enumCTL(WINECRYPT_CERTSTORE *store, context_t *prev)
 {
-    PWINE_COLLECTIONSTORE cs = (PWINE_COLLECTIONSTORE)store;
+    WINE_COLLECTIONSTORE *cs = (WINE_COLLECTIONSTORE*)store;
     void *ret;
 
-    TRACE("(%p, %p)\n", store, pPrev);
+    TRACE("(%p, %p)\n", store, prev);
 
     EnterCriticalSection(&cs->cs);
-    if (pPrev)
+    if (prev)
     {
-        PWINE_STORE_LIST_ENTRY storeEntry =
-         *(PWINE_STORE_LIST_ENTRY *)Context_GetExtra(pPrev,
-         sizeof(CTL_CONTEXT));
+        WINE_STORE_LIST_ENTRY *storeEntry = prev->u.ptr;
 
         ret = CRYPT_CollectionAdvanceEnum(cs, storeEntry,
-         &storeEntry->store->ctls, pCTLInterface, pPrev, sizeof(CTL_CONTEXT));
+         &storeEntry->store->vtbl->ctls, prev);
     }
     else
     {
         if (!list_empty(&cs->stores))
         {
-            PWINE_STORE_LIST_ENTRY storeEntry = LIST_ENTRY(cs->stores.next,
+            WINE_STORE_LIST_ENTRY *storeEntry = LIST_ENTRY(cs->stores.next,
              WINE_STORE_LIST_ENTRY, entry);
 
             ret = CRYPT_CollectionAdvanceEnum(cs, storeEntry,
-             &storeEntry->store->ctls, pCTLInterface, NULL,
-             sizeof(CTL_CONTEXT));
+             &storeEntry->store->vtbl->ctls, NULL);
         }
         else
         {
@@ -411,40 +387,28 @@ static void *CRYPT_CollectionEnumCTL(PWINECRYPT_CERTSTORE store, void *pPrev)
         }
     }
     LeaveCriticalSection(&cs->cs);
-    if (ret)
-        ((PCTL_CONTEXT)ret)->hCertStore = store;
     TRACE("returning %p\n", ret);
     return ret;
 }
 
-static BOOL CRYPT_CollectionDeleteCTL(PWINECRYPT_CERTSTORE store,
- void *pCtlContext)
+static BOOL Collection_deleteCTL(WINECRYPT_CERTSTORE *store, context_t *context)
 {
-    BOOL ret;
-    PCCTL_CONTEXT linked;
-
-    TRACE("(%p, %p)\n", store, pCtlContext);
-
-    /* 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;
+    ctl_t *ctl = (ctl_t*)context, *linked;
+
+    TRACE("(%p, %p)\n", store, ctl);
+
+    linked = (ctl_t*)context->linked;
+    return CertDeleteCTLFromStore(&linked->ctx);
 }
 
-static BOOL WINAPI CRYPT_CollectionControl(HCERTSTORE hCertStore, DWORD dwFlags,
+static BOOL Collection_control(WINECRYPT_CERTSTORE *cert_store, DWORD dwFlags,
  DWORD dwCtrlType, void const *pvCtrlPara)
 {
     BOOL ret;
-    PWINE_COLLECTIONSTORE store = hCertStore;
-    PWINE_STORE_LIST_ENTRY entry;
+    WINE_COLLECTIONSTORE *store = (WINE_COLLECTIONSTORE*)cert_store;
+    WINE_STORE_LIST_ENTRY *entry;
 
-    TRACE("(%p, %08x, %d, %p)\n", hCertStore, dwFlags, dwCtrlType,
-     pvCtrlPara);
+    TRACE("(%p, %08x, %d, %p)\n", cert_store, dwFlags, dwCtrlType, pvCtrlPara);
 
     if (!store)
         return TRUE;
@@ -463,10 +427,9 @@ static BOOL WINAPI CRYPT_CollectionControl(HCERTSTORE hCertStore, DWORD dwFlags,
     EnterCriticalSection(&store->cs);
     LIST_FOR_EACH_ENTRY(entry, &store->stores, WINE_STORE_LIST_ENTRY, entry)
     {
-        if (entry->store->control)
+        if (entry->store->vtbl->control)
         {
-            ret = entry->store->control(entry->store, dwFlags, dwCtrlType,
-             pvCtrlPara);
+            ret = entry->store->vtbl->control(entry->store, dwFlags, dwCtrlType, pvCtrlPara);
             if (!ret)
                 break;
         }
@@ -475,10 +438,30 @@ static BOOL WINAPI CRYPT_CollectionControl(HCERTSTORE hCertStore, DWORD dwFlags,
     return ret;
 }
 
-PWINECRYPT_CERTSTORE CRYPT_CollectionOpenStore(HCRYPTPROV hCryptProv,
+static const store_vtbl_t CollectionStoreVtbl = {
+    Collection_addref,
+    Collection_release,
+    Collection_releaseContext,
+    Collection_control,
+    {
+        Collection_addCert,
+        Collection_enumCert,
+        Collection_deleteCert
+    }, {
+        Collection_addCRL,
+        Collection_enumCRL,
+        Collection_deleteCRL
+    }, {
+        Collection_addCTL,
+        Collection_enumCTL,
+        Collection_deleteCTL
+    }
+};
+
+WINECRYPT_CERTSTORE *CRYPT_CollectionOpenStore(HCRYPTPROV hCryptProv,
  DWORD dwFlags, const void *pvPara)
 {
-    PWINE_COLLECTIONSTORE store;
+    WINE_COLLECTIONSTORE *store;
 
     if (dwFlags & CERT_STORE_DELETE_FLAG)
     {
@@ -491,32 +474,21 @@ PWINECRYPT_CERTSTORE CRYPT_CollectionOpenStore(HCRYPTPROV hCryptProv,
         if (store)
         {
             memset(store, 0, sizeof(WINE_COLLECTIONSTORE));
-            CRYPT_InitStore(&store->hdr, dwFlags, StoreTypeCollection);
-            store->hdr.closeStore          = CRYPT_CollectionCloseStore;
-            store->hdr.certs.addContext    = CRYPT_CollectionAddCert;
-            store->hdr.certs.enumContext   = CRYPT_CollectionEnumCert;
-            store->hdr.certs.deleteContext = CRYPT_CollectionDeleteCert;
-            store->hdr.crls.addContext     = CRYPT_CollectionAddCRL;
-            store->hdr.crls.enumContext    = CRYPT_CollectionEnumCRL;
-            store->hdr.crls.deleteContext  = CRYPT_CollectionDeleteCRL;
-            store->hdr.ctls.addContext     = CRYPT_CollectionAddCTL;
-            store->hdr.ctls.enumContext    = CRYPT_CollectionEnumCTL;
-            store->hdr.ctls.deleteContext  = CRYPT_CollectionDeleteCTL;
-            store->hdr.control             = CRYPT_CollectionControl;
+            CRYPT_InitStore(&store->hdr, dwFlags, StoreTypeCollection, &CollectionStoreVtbl);
             InitializeCriticalSection(&store->cs);
             store->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": PWINE_COLLECTIONSTORE->cs");
             list_init(&store->stores);
         }
     }
-    return (PWINECRYPT_CERTSTORE)store;
+    return (WINECRYPT_CERTSTORE*)store;
 }
 
 BOOL WINAPI CertAddStoreToCollection(HCERTSTORE hCollectionStore,
  HCERTSTORE hSiblingStore, DWORD dwUpdateFlags, DWORD dwPriority)
 {
-    PWINE_COLLECTIONSTORE collection = hCollectionStore;
+    WINE_COLLECTIONSTORE *collection = hCollectionStore;
     WINECRYPT_CERTSTORE *sibling = hSiblingStore;
-    PWINE_STORE_LIST_ENTRY entry;
+    WINE_STORE_LIST_ENTRY *entry;
     BOOL ret;
 
     TRACE("(%p, %p, %08x, %d)\n", hCollectionStore, hSiblingStore,
@@ -553,7 +525,7 @@ BOOL WINAPI CertAddStoreToCollection(HCERTSTORE hCollectionStore,
         EnterCriticalSection(&collection->cs);
         if (dwPriority)
         {
-            PWINE_STORE_LIST_ENTRY cursor;
+            WINE_STORE_LIST_ENTRY *cursor;
             BOOL added = FALSE;
 
             LIST_FOR_EACH_ENTRY(cursor, &collection->stores,
@@ -582,9 +554,9 @@ BOOL WINAPI CertAddStoreToCollection(HCERTSTORE hCollectionStore,
 void WINAPI CertRemoveStoreFromCollection(HCERTSTORE hCollectionStore,
  HCERTSTORE hSiblingStore)
 {
-    PWINE_COLLECTIONSTORE collection = hCollectionStore;
+    WINE_COLLECTIONSTORE *collection = hCollectionStore;
     WINECRYPT_CERTSTORE *sibling = hSiblingStore;
-    PWINE_STORE_LIST_ENTRY store, next;
+    WINE_STORE_LIST_ENTRY *store, *next;
 
     TRACE("(%p, %p)\n", hCollectionStore, hSiblingStore);
 
index 2fe8642..e0824f5 100644 (file)
 
 WINE_DEFAULT_DEBUG_CHANNEL(context);
 
-typedef enum _ContextType {
-    ContextTypeData,
-    ContextTypeLink,
-} ContextType;
-
-typedef struct _BASE_CONTEXT
-{
-    LONG        ref;
-    ContextType type;
-} BASE_CONTEXT, *PBASE_CONTEXT;
-
-typedef struct _DATA_CONTEXT
-{
-    LONG                   ref;
-    ContextType            type; /* always ContextTypeData */
-    PCONTEXT_PROPERTY_LIST properties;
-} DATA_CONTEXT, *PDATA_CONTEXT;
-
-typedef struct _LINK_CONTEXT
+context_t *Context_CreateDataContext(size_t contextSize, const context_vtbl_t *vtbl, WINECRYPT_CERTSTORE *store)
 {
-    LONG          ref;
-    ContextType   type; /* always ContextTypeLink */
-    PBASE_CONTEXT linked;
-} LINK_CONTEXT, *PLINK_CONTEXT;
+    context_t *context;
 
-#define CONTEXT_FROM_BASE_CONTEXT(p, s) ((LPBYTE)(p) - (s))
-#define BASE_CONTEXT_FROM_CONTEXT(p, s) (PBASE_CONTEXT)((LPBYTE)(p) + (s))
+    context = CryptMemAlloc(sizeof(context_t) + contextSize);
+    if (!context)
+        return NULL;
 
-void *Context_CreateDataContext(size_t contextSize)
-{
-    void *ret = CryptMemAlloc(contextSize + sizeof(DATA_CONTEXT));
-
-    if (ret)
+    context->properties = ContextPropertyList_Create();
+    if (!context->properties)
     {
-        PDATA_CONTEXT context = (PDATA_CONTEXT)((LPBYTE)ret + contextSize);
-
-        context->ref = 1;
-        context->type = ContextTypeData;
-        context->properties = ContextPropertyList_Create();
-        if (!context->properties)
-        {
-            CryptMemFree(ret);
-            ret = NULL;
-        }
+        CryptMemFree(context);
+        return NULL;
     }
-    TRACE("returning %p\n", ret);
-    return ret;
-}
 
-void *Context_CreateLinkContext(unsigned int contextSize, void *linked, unsigned int extra,
- BOOL addRef)
-{
-    void *context = CryptMemAlloc(contextSize + sizeof(LINK_CONTEXT) + extra);
-
-    TRACE("(%d, %p, %d)\n", contextSize, linked, extra);
+    context->vtbl = vtbl;
+    context->ref = 1;
+    context->linked = NULL;
 
-    if (context)
-    {
-        PLINK_CONTEXT linkContext = (PLINK_CONTEXT)BASE_CONTEXT_FROM_CONTEXT(
-         context, contextSize);
-        PBASE_CONTEXT linkedBase = BASE_CONTEXT_FROM_CONTEXT(linked,
-         contextSize);
+    store->vtbl->addref(store);
+    context->store = store;
 
-        memcpy(context, linked, contextSize);
-        linkContext->ref = 1;
-        linkContext->type = ContextTypeLink;
-        linkContext->linked = linkedBase;
-        if (addRef)
-            Context_AddRef(linked, contextSize);
-        TRACE("%p's ref count is %d\n", context, linkContext->ref);
-    }
     TRACE("returning %p\n", context);
     return context;
 }
 
-void Context_AddRef(void *context, size_t contextSize)
+context_t *Context_CreateLinkContext(unsigned int contextSize, context_t *linked, WINECRYPT_CERTSTORE *store)
 {
-    PBASE_CONTEXT baseContext = BASE_CONTEXT_FROM_CONTEXT(context, contextSize);
+    context_t *context;
 
-    InterlockedIncrement(&baseContext->ref);
-    TRACE("%p's ref count is %d\n", context, baseContext->ref);
-    if (baseContext->type == ContextTypeLink)
-    {
-        void *linkedContext = Context_GetLinkedContext(context, contextSize);
-        PBASE_CONTEXT linkedBase = BASE_CONTEXT_FROM_CONTEXT(linkedContext,
-         contextSize);
+    TRACE("(%d, %p)\n", contextSize, linked);
 
-        /* Add-ref the linked contexts too */
-        while (linkedContext && linkedBase->type == ContextTypeLink)
-        {
-            InterlockedIncrement(&linkedBase->ref);
-            TRACE("%p's ref count is %d\n", linkedContext, linkedBase->ref);
-            linkedContext = Context_GetLinkedContext(linkedContext,
-             contextSize);
-            if (linkedContext)
-                linkedBase = BASE_CONTEXT_FROM_CONTEXT(linkedContext,
-                 contextSize);
-            else
-                linkedBase = NULL;
-        }
-        if (linkedContext)
-        {
-            /* It's not a link context, so it wasn't add-ref'ed in the while
-             * loop, so add-ref it here.
-             */
-            linkedBase = BASE_CONTEXT_FROM_CONTEXT(linkedContext,
-             contextSize);
-            InterlockedIncrement(&linkedBase->ref);
-            TRACE("%p's ref count is %d\n", linkedContext, linkedBase->ref);
-        }
-    }
-}
+    context = CryptMemAlloc(sizeof(context_t) + contextSize);
+    if (!context)
+        return NULL;
 
-void *Context_GetExtra(const void *context, size_t contextSize)
-{
-    PBASE_CONTEXT baseContext = BASE_CONTEXT_FROM_CONTEXT(context, contextSize);
+    memcpy(context_ptr(context), context_ptr(linked), contextSize);
+    context->vtbl = linked->vtbl;
+    context->ref = 1;
+    context->linked = linked;
+    context->properties = linked->properties;
+    Context_AddRef(linked);
 
-    assert(baseContext->type == ContextTypeLink);
-    return (LPBYTE)baseContext + sizeof(LINK_CONTEXT);
-}
+    store->vtbl->addref(store);
+    context->store = store;
 
-void *Context_GetLinkedContext(void *context, size_t contextSize)
-{
-    PBASE_CONTEXT baseContext = BASE_CONTEXT_FROM_CONTEXT(context, contextSize);
-
-    assert(baseContext->type == ContextTypeLink);
-    return CONTEXT_FROM_BASE_CONTEXT(((PLINK_CONTEXT)baseContext)->linked,
-     contextSize);
+    TRACE("returning %p\n", context);
+    return context;
 }
 
-PCONTEXT_PROPERTY_LIST Context_GetProperties(const void *context, size_t contextSize)
+void Context_AddRef(context_t *context)
 {
-    PBASE_CONTEXT ptr = BASE_CONTEXT_FROM_CONTEXT(context, contextSize);
+    LONG ref = InterlockedIncrement(&context->ref);
 
-    while (ptr && ptr->type == ContextTypeLink)
-        ptr = ((PLINK_CONTEXT)ptr)->linked;
-    return (ptr && ptr->type == ContextTypeData) ?
-     ((PDATA_CONTEXT)ptr)->properties : NULL;
-}
+    TRACE("(%p) ref=%d\n", context, context->ref);
 
-BOOL Context_Release(void *context, size_t contextSize,
- ContextFreeFunc dataContextFree)
-{
-    PBASE_CONTEXT base = BASE_CONTEXT_FROM_CONTEXT(context, contextSize);
-    BOOL ret = TRUE;
-
-    if (base->ref <= 0)
-    {
-        ERR("%p's ref count is %d\n", context, base->ref);
-        return FALSE;
-    }
-    if (base->type == ContextTypeLink)
-    {
-        /* The linked context is of the same type as this, so release
-         * it as well, using the same offset and data free function.
-         */
-        ret = Context_Release(CONTEXT_FROM_BASE_CONTEXT(
-         ((PLINK_CONTEXT)base)->linked, contextSize), contextSize,
-         dataContextFree);
+    if(ref == 1) {
+        /* This is the first external (non-store) reference. Increase store ref cnt. */
+        context->store->vtbl->addref(context->store);
     }
-    if (InterlockedDecrement(&base->ref) == 0)
-    {
-        TRACE("freeing %p\n", context);
-        if (base->type == ContextTypeData)
-        {
-            ContextPropertyList_Free(((PDATA_CONTEXT)base)->properties);
-            dataContextFree(context);
-        }
-        CryptMemFree(context);
-    }
-    else
-        TRACE("%p's ref count is %d\n", context, base->ref);
-    return ret;
 }
 
-void Context_CopyProperties(const void *to, const void *from,
- size_t contextSize)
+void Context_Free(context_t *context)
 {
-    PCONTEXT_PROPERTY_LIST toProperties, fromProperties;
+    TRACE("(%p)\n", context);
 
-    toProperties = Context_GetProperties(to, contextSize);
-    fromProperties = Context_GetProperties(from, contextSize);
-    assert(toProperties && fromProperties);
-    ContextPropertyList_Copy(toProperties, fromProperties);
-}
-
-struct ContextList
-{
-    PCWINE_CONTEXT_INTERFACE contextInterface;
-    size_t contextSize;
-    CRITICAL_SECTION cs;
-    struct list contexts;
-};
+    assert(!context->ref);
 
-struct ContextList *ContextList_Create(
- PCWINE_CONTEXT_INTERFACE contextInterface, size_t contextSize)
-{
-    struct ContextList *list = CryptMemAlloc(sizeof(struct ContextList));
-
-    if (list)
-    {
-        list->contextInterface = contextInterface;
-        list->contextSize = contextSize;
-        InitializeCriticalSection(&list->cs);
-        list->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": ContextList.cs");
-        list_init(&list->contexts);
+    if (!context->linked) {
+        ContextPropertyList_Free(context->properties);
+        context->vtbl->free(context);
+    }else {
+        Context_Release(context->linked);
     }
-    return list;
-}
-
-static inline struct list *ContextList_ContextToEntry(const struct ContextList *list,
- const void *context)
-{
-    struct list *ret;
-
-    if (context)
-        ret = Context_GetExtra(context, list->contextSize);
-    else
-        ret = NULL;
-    return ret;
-}
-
-static inline void *ContextList_EntryToContext(const struct ContextList *list,
- struct list *entry)
-{
-    return (LPBYTE)entry - sizeof(LINK_CONTEXT) - list->contextSize;
-}
-
-void *ContextList_Add(struct ContextList *list, void *toLink, void *toReplace)
-{
-    void *context;
-
-    TRACE("(%p, %p, %p)\n", list, toLink, toReplace);
 
-    context = Context_CreateLinkContext(list->contextSize, toLink,
-     sizeof(struct list), TRUE);
-    if (context)
-    {
-        struct list *entry = ContextList_ContextToEntry(list, context);
-
-        TRACE("adding %p\n", context);
-        EnterCriticalSection(&list->cs);
-        if (toReplace)
-        {
-            struct list *existing = ContextList_ContextToEntry(list, toReplace);
-
-            entry->prev = existing->prev;
-            entry->next = existing->next;
-            entry->prev->next = entry;
-            entry->next->prev = entry;
-            existing->prev = existing->next = existing;
-            list->contextInterface->free(toReplace);
-        }
-        else
-            list_add_head(&list->contexts, entry);
-        LeaveCriticalSection(&list->cs);
-    }
-    return context;
+    CryptMemFree(context);
 }
 
-void *ContextList_Enum(struct ContextList *list, void *pPrev)
+void Context_Release(context_t *context)
 {
-    struct list *listNext;
-    void *ret;
+    LONG ref = InterlockedDecrement(&context->ref);
 
-    EnterCriticalSection(&list->cs);
-    if (pPrev)
-    {
-        struct list *prevEntry = ContextList_ContextToEntry(list, pPrev);
+    TRACE("(%p) ref=%d\n", context, ref);
+    assert(ref >= 0);
 
-        listNext = list_next(&list->contexts, prevEntry);
-        list->contextInterface->free(pPrev);
-    }
-    else
-        listNext = list_next(&list->contexts, &list->contexts);
-    LeaveCriticalSection(&list->cs);
-
-    if (listNext)
-    {
-        ret = ContextList_EntryToContext(list, listNext);
-        list->contextInterface->duplicate(ret);
-    }
-    else
-        ret = NULL;
-    return ret;
-}
-
-BOOL ContextList_Remove(struct ContextList *list, void *context)
-{
-    struct list *entry = ContextList_ContextToEntry(list, context);
-    BOOL inList = FALSE;
+    if (!ref) {
+        WINECRYPT_CERTSTORE *store = context->store;
 
-    EnterCriticalSection(&list->cs);
-    if (!list_empty(entry))
-    {
-        list_remove(entry);
-        inList = TRUE;
+        /* This is the last reference, but the context still may be in a store.
+         * We release our store reference, but leave it up to store to free or keep the context. */
+        store->vtbl->releaseContext(store, context);
+        store->vtbl->release(store, 0);
     }
-    LeaveCriticalSection(&list->cs);
-    if (inList)
-        list_init(entry);
-    return inList;
 }
 
-static void ContextList_Empty(struct ContextList *list)
+void Context_CopyProperties(const void *to, const void *from)
 {
-    struct list *entry, *next;
-
-    EnterCriticalSection(&list->cs);
-    LIST_FOR_EACH_SAFE(entry, next, &list->contexts)
-    {
-        const void *context = ContextList_EntryToContext(list, entry);
+    CONTEXT_PROPERTY_LIST *toProperties, *fromProperties;
 
-        TRACE("removing %p\n", context);
-        list_remove(entry);
-        list->contextInterface->free(context);
-    }
-    LeaveCriticalSection(&list->cs);
-}
-
-void ContextList_Free(struct ContextList *list)
-{
-    ContextList_Empty(list);
-    list->cs.DebugInfo->Spare[0] = 0;
-    DeleteCriticalSection(&list->cs);
-    CryptMemFree(list);
+    toProperties = context_from_ptr(to)->properties;
+    fromProperties = context_from_ptr(from)->properties;
+    assert(toProperties && fromProperties);
+    ContextPropertyList_Copy(toProperties, fromProperties);
 }
index 6432672..ada6bea 100644 (file)
 
 WINE_DEFAULT_DEBUG_CHANNEL(crypt);
 
+static void CRL_free(context_t *context)
+{
+    crl_t *crl = (crl_t*)context;
+
+    CryptMemFree(crl->ctx.pbCrlEncoded);
+    LocalFree(crl->ctx.pCrlInfo);
+}
+
+static const context_vtbl_t crl_vtbl;
+
+static context_t *CRL_clone(context_t *context, WINECRYPT_CERTSTORE *store, BOOL use_link)
+{
+    crl_t *crl;
+
+    if(use_link) {
+        crl = (crl_t*)Context_CreateLinkContext(sizeof(CRL_CONTEXT), context, store);
+        if(!crl)
+            return NULL;
+    }else {
+        const crl_t *cloned = (const crl_t*)context;
+        DWORD size = 0;
+        BOOL res;
+
+        crl = (crl_t*)Context_CreateDataContext(sizeof(CRL_CONTEXT), &crl_vtbl, store);
+        if(!crl)
+            return NULL;
+
+        Context_CopyProperties(&crl->ctx, &cloned->ctx);
+
+        crl->ctx.dwCertEncodingType = cloned->ctx.dwCertEncodingType;
+        crl->ctx.pbCrlEncoded = CryptMemAlloc(cloned->ctx.cbCrlEncoded);
+        memcpy(crl->ctx.pbCrlEncoded, cloned->ctx.pbCrlEncoded, cloned->ctx.cbCrlEncoded);
+        crl->ctx.cbCrlEncoded = cloned->ctx.cbCrlEncoded;
+
+        /* FIXME: We don't need to decode the object here, we could just clone crl info. */
+        res = CryptDecodeObjectEx(crl->ctx.dwCertEncodingType, X509_CERT_CRL_TO_BE_SIGNED,
+         crl->ctx.pbCrlEncoded, crl->ctx.cbCrlEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL,
+         &crl->ctx.pCrlInfo, &size);
+        if(!res) {
+            CertFreeCRLContext(&crl->ctx);
+            return NULL;
+        }
+    }
+
+    crl->ctx.hCertStore = store;
+    return &crl->base;
+}
+
+static const context_vtbl_t crl_vtbl = {
+    CRL_free,
+    CRL_clone
+};
+
 PCCRL_CONTEXT WINAPI CertCreateCRLContext(DWORD dwCertEncodingType,
  const BYTE* pbCrlEncoded, DWORD cbCrlEncoded)
 {
-    PCRL_CONTEXT crl = NULL;
+    crl_t *crl = NULL;
     BOOL ret;
     PCRL_INFO crlInfo = NULL;
+    BYTE *data = NULL;
     DWORD size = 0;
 
     TRACE("(%08x, %p, %d)\n", dwCertEncodingType, pbCrlEncoded,
@@ -40,30 +94,28 @@ PCCRL_CONTEXT WINAPI CertCreateCRLContext(DWORD dwCertEncodingType,
     ret = CryptDecodeObjectEx(dwCertEncodingType, X509_CERT_CRL_TO_BE_SIGNED,
      pbCrlEncoded, cbCrlEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL,
      &crlInfo, &size);
-    if (ret)
-    {
-        BYTE *data = NULL;
+    if (!ret)
+        return NULL;
 
-        crl = Context_CreateDataContext(sizeof(CRL_CONTEXT));
-        if (!crl)
-            goto end;
-        data = CryptMemAlloc(cbCrlEncoded);
-        if (!data)
-        {
-            CertFreeCRLContext(crl);
-            crl = NULL;
-            goto end;
-        }
-        memcpy(data, pbCrlEncoded, cbCrlEncoded);
-        crl->dwCertEncodingType = dwCertEncodingType;
-        crl->pbCrlEncoded       = data;
-        crl->cbCrlEncoded       = cbCrlEncoded;
-        crl->pCrlInfo           = crlInfo;
-        crl->hCertStore         = 0;
+    crl = (crl_t*)Context_CreateDataContext(sizeof(CRL_CONTEXT), &crl_vtbl, &empty_store);
+    if (!crl)
+        return NULL;
+
+    data = CryptMemAlloc(cbCrlEncoded);
+    if (!data)
+    {
+        Context_Release(&crl->base);
+        return NULL;
     }
 
-end:
-    return crl;
+    memcpy(data, pbCrlEncoded, cbCrlEncoded);
+    crl->ctx.dwCertEncodingType = dwCertEncodingType;
+    crl->ctx.pbCrlEncoded       = data;
+    crl->ctx.cbCrlEncoded       = cbCrlEncoded;
+    crl->ctx.pCrlInfo           = crlInfo;
+    crl->ctx.hCertStore         = &empty_store;
+
+    return &crl->ctx;
 }
 
 BOOL WINAPI CertAddEncodedCRLToStore(HCERTSTORE hCertStore,
@@ -319,50 +371,31 @@ PCCRL_CONTEXT WINAPI CertDuplicateCRLContext(PCCRL_CONTEXT pCrlContext)
 {
     TRACE("(%p)\n", pCrlContext);
     if (pCrlContext)
-        Context_AddRef((void *)pCrlContext, sizeof(CRL_CONTEXT));
+        Context_AddRef(&crl_from_ptr(pCrlContext)->base);
     return pCrlContext;
 }
 
-static void CrlDataContext_Free(void *context)
+BOOL WINAPI CertFreeCRLContext(PCCRL_CONTEXT pCrlContext)
 {
-    PCRL_CONTEXT crlContext = context;
-
-    CryptMemFree(crlContext->pbCrlEncoded);
-    LocalFree(crlContext->pCrlInfo);
-}
-
-BOOL WINAPI CertFreeCRLContext( PCCRL_CONTEXT pCrlContext)
-{
-    BOOL ret = TRUE;
-
     TRACE("(%p)\n", pCrlContext);
 
     if (pCrlContext)
-        ret = Context_Release((void *)pCrlContext, sizeof(CRL_CONTEXT),
-         CrlDataContext_Free);
-    return ret;
+        Context_Release(&crl_from_ptr(pCrlContext)->base);
+    return TRUE;
 }
 
 DWORD WINAPI CertEnumCRLContextProperties(PCCRL_CONTEXT pCRLContext,
  DWORD dwPropId)
 {
-    PCONTEXT_PROPERTY_LIST properties = Context_GetProperties(
-     pCRLContext, sizeof(CRL_CONTEXT));
-    DWORD ret;
-
     TRACE("(%p, %d)\n", pCRLContext, dwPropId);
 
-    if (properties)
-        ret = ContextPropertyList_EnumPropIDs(properties, dwPropId);
-    else
-        ret = 0;
-    return ret;
+    return ContextPropertyList_EnumPropIDs(crl_from_ptr(pCRLContext)->base.properties, dwPropId);
 }
 
-static BOOL CRLContext_SetProperty(PCCRL_CONTEXT context, DWORD dwPropId,
+static BOOL CRLContext_SetProperty(crl_t *crl, DWORD dwPropId,
                                    DWORD dwFlags, const void *pvData);
 
-static BOOL CRLContext_GetHashProp(PCCRL_CONTEXT context, DWORD dwPropId,
+static BOOL CRLContext_GetHashProp(crl_t *crl, DWORD dwPropId,
  ALG_ID algID, const BYTE *toHash, DWORD toHashLen, void *pvData,
  DWORD *pcbData)
 {
@@ -372,23 +405,21 @@ static BOOL CRLContext_GetHashProp(PCCRL_CONTEXT context, DWORD dwPropId,
     {
         CRYPT_DATA_BLOB blob = { *pcbData, pvData };
 
-        ret = CRLContext_SetProperty(context, dwPropId, 0, &blob);
+        ret = CRLContext_SetProperty(crl, dwPropId, 0, &blob);
     }
     return ret;
 }
 
-static BOOL CRLContext_GetProperty(PCCRL_CONTEXT context, DWORD dwPropId,
+static BOOL CRLContext_GetProperty(crl_t *crl, DWORD dwPropId,
                                    void *pvData, DWORD *pcbData)
 {
-    PCONTEXT_PROPERTY_LIST properties =
-     Context_GetProperties(context, sizeof(CRL_CONTEXT));
     BOOL ret;
     CRYPT_DATA_BLOB blob;
 
-    TRACE("(%p, %d, %p, %p)\n", context, dwPropId, pvData, pcbData);
+    TRACE("(%p, %d, %p, %p)\n", crl, dwPropId, pvData, pcbData);
 
-    if (properties)
-        ret = ContextPropertyList_FindProperty(properties, dwPropId, &blob);
+    if (crl->base.properties)
+        ret = ContextPropertyList_FindProperty(crl->base.properties, dwPropId, &blob);
     else
         ret = FALSE;
     if (ret)
@@ -413,13 +444,13 @@ static BOOL CRLContext_GetProperty(PCCRL_CONTEXT context, DWORD dwPropId,
         switch (dwPropId)
         {
         case CERT_SHA1_HASH_PROP_ID:
-            ret = CRLContext_GetHashProp(context, dwPropId, CALG_SHA1,
-                                         context->pbCrlEncoded, context->cbCrlEncoded, pvData,
+            ret = CRLContext_GetHashProp(crl, dwPropId, CALG_SHA1,
+                                         crl->ctx.pbCrlEncoded, crl->ctx.cbCrlEncoded, pvData,
              pcbData);
             break;
         case CERT_MD5_HASH_PROP_ID:
-            ret = CRLContext_GetHashProp(context, dwPropId, CALG_MD5,
-                                         context->pbCrlEncoded, context->cbCrlEncoded, pvData,
+            ret = CRLContext_GetHashProp(crl, dwPropId, CALG_MD5,
+                                         crl->ctx.pbCrlEncoded, crl->ctx.cbCrlEncoded, pvData,
              pcbData);
             break;
         default:
@@ -460,37 +491,27 @@ BOOL WINAPI CertGetCRLContextProperty(PCCRL_CONTEXT pCRLContext,
         }
         else
         {
-            if (pCRLContext->hCertStore)
-                ret = CertGetStoreProperty(pCRLContext->hCertStore, dwPropId,
-                 pvData, pcbData);
-            else
-            {
-                *(DWORD *)pvData = 0;
-                ret = TRUE;
-            }
+            ret = CertGetStoreProperty(pCRLContext->hCertStore, dwPropId, pvData, pcbData);
         }
         break;
     default:
-        ret = CRLContext_GetProperty(pCRLContext, dwPropId, pvData,
-         pcbData);
+        ret = CRLContext_GetProperty(crl_from_ptr(pCRLContext), dwPropId, pvData, pcbData);
     }
     return ret;
 }
 
-static BOOL CRLContext_SetProperty(PCCRL_CONTEXT context, DWORD dwPropId,
+static BOOL CRLContext_SetProperty(crl_t *crl, DWORD dwPropId,
  DWORD dwFlags, const void *pvData)
 {
-    PCONTEXT_PROPERTY_LIST properties =
-     Context_GetProperties(context, sizeof(CRL_CONTEXT));
     BOOL ret;
 
-    TRACE("(%p, %d, %08x, %p)\n", context, dwPropId, dwFlags, pvData);
+    TRACE("(%p, %d, %08x, %p)\n", crl, dwPropId, dwFlags, pvData);
 
-    if (!properties)
+    if (!crl->base.properties)
         ret = FALSE;
     else if (!pvData)
     {
-        ContextPropertyList_RemoveProperty(properties, dwPropId);
+        ContextPropertyList_RemoveProperty(crl->base.properties, dwPropId);
         ret = TRUE;
     }
     else
@@ -517,12 +538,12 @@ static BOOL CRLContext_SetProperty(PCCRL_CONTEXT context, DWORD dwPropId,
         {
             PCRYPT_DATA_BLOB blob = (PCRYPT_DATA_BLOB)pvData;
 
-            ret = ContextPropertyList_SetProperty(properties, dwPropId,
+            ret = ContextPropertyList_SetProperty(crl->base.properties, dwPropId,
              blob->pbData, blob->cbData);
             break;
         }
         case CERT_DATE_STAMP_PROP_ID:
-            ret = ContextPropertyList_SetProperty(properties, dwPropId,
+            ret = ContextPropertyList_SetProperty(crl->base.properties, dwPropId,
              pvData, sizeof(FILETIME));
             break;
         default:
@@ -554,7 +575,7 @@ BOOL WINAPI CertSetCRLContextProperty(PCCRL_CONTEXT pCRLContext,
         SetLastError(E_INVALIDARG);
         return FALSE;
     }
-    ret = CRLContext_SetProperty(pCRLContext, dwPropId, dwFlags, pvData);
+    ret = CRLContext_SetProperty(crl_from_ptr(pCRLContext), dwPropId, dwFlags, pvData);
     TRACE("returning %d\n", ret);
     return ret;
 }
index 3224987..aa20cc8 100644 (file)
@@ -188,6 +188,70 @@ void crypt_sip_free(void) DECLSPEC_HIDDEN;
 void root_store_free(void) DECLSPEC_HIDDEN;
 void default_chain_engine_free(void) DECLSPEC_HIDDEN;
 
+/* (Internal) certificate store types and functions */
+struct WINE_CRYPTCERTSTORE;
+
+typedef struct _CONTEXT_PROPERTY_LIST CONTEXT_PROPERTY_LIST;
+
+typedef struct _context_t context_t;
+
+typedef struct {
+    void (*free)(context_t*);
+    struct _context_t *(*clone)(context_t*,struct WINE_CRYPTCERTSTORE*,BOOL);
+} context_vtbl_t;
+
+struct _context_t {
+    const context_vtbl_t *vtbl;
+    LONG ref;
+    struct WINE_CRYPTCERTSTORE *store;
+    struct _context_t *linked;
+    CONTEXT_PROPERTY_LIST *properties;
+    union {
+        struct list entry;
+        void *ptr;
+    } u;
+};
+
+static inline context_t *context_from_ptr(const void *ptr)
+{
+    return (context_t*)ptr-1;
+}
+
+static inline void *context_ptr(context_t *context)
+{
+    return context+1;
+}
+
+typedef struct {
+    context_t base;
+    CERT_CONTEXT ctx;
+} cert_t;
+
+static inline cert_t *cert_from_ptr(const CERT_CONTEXT *ptr)
+{
+    return CONTAINING_RECORD(ptr, cert_t, ctx);
+}
+
+typedef struct {
+    context_t base;
+    CRL_CONTEXT ctx;
+} crl_t;
+
+static inline crl_t *crl_from_ptr(const CRL_CONTEXT *ptr)
+{
+    return CONTAINING_RECORD(ptr, crl_t, ctx);
+}
+
+typedef struct {
+    context_t base;
+    CTL_CONTEXT ctx;
+} ctl_t;
+
+static inline ctl_t *ctl_from_ptr(const CTL_CONTEXT *ptr)
+{
+    return CONTAINING_RECORD(ptr, ctl_t, ctx);
+}
+
 /* Some typedefs that make it easier to abstract which type of context we're
  * working with.
  */
@@ -198,7 +262,6 @@ typedef BOOL (WINAPI *AddContextToStoreFunc)(HCERTSTORE hCertStore,
 typedef BOOL (WINAPI *AddEncodedContextToStoreFunc)(HCERTSTORE hCertStore,
  DWORD dwCertEncodingType, const BYTE *pbEncoded, DWORD cbEncoded,
  DWORD dwAddDisposition, const void **ppContext);
-typedef const void *(WINAPI *DuplicateContextFunc)(const void *context);
 typedef const void *(WINAPI *EnumContextsInStoreFunc)(HCERTSTORE hCertStore,
  const void *pPrevContext);
 typedef DWORD (WINAPI *EnumPropertiesFunc)(const void *context, DWORD dwPropId);
@@ -208,7 +271,6 @@ 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 *contex);
 
 /* An abstract context (certificate, CRL, or CTL) interface */
@@ -217,57 +279,41 @@ typedef struct _WINE_CONTEXT_INTERFACE
     CreateContextFunc            create;
     AddContextToStoreFunc        addContextToStore;
     AddEncodedContextToStoreFunc addEncodedToStore;
-    DuplicateContextFunc         duplicate;
     EnumContextsInStoreFunc      enumContextsInStore;
     EnumPropertiesFunc           enumProps;
     GetContextPropertyFunc       getProp;
     SetContextPropertyFunc       setProp;
     SerializeElementFunc         serialize;
-    FreeContextFunc              free;
     DeleteContextFunc            deleteFromStore;
-} WINE_CONTEXT_INTERFACE, *PWINE_CONTEXT_INTERFACE;
-typedef const WINE_CONTEXT_INTERFACE *PCWINE_CONTEXT_INTERFACE;
+} WINE_CONTEXT_INTERFACE;
 
-extern PCWINE_CONTEXT_INTERFACE pCertInterface DECLSPEC_HIDDEN;
-extern PCWINE_CONTEXT_INTERFACE pCRLInterface DECLSPEC_HIDDEN;
-extern PCWINE_CONTEXT_INTERFACE pCTLInterface DECLSPEC_HIDDEN;
-
-/* (Internal) certificate store types and functions */
-struct WINE_CRYPTCERTSTORE;
+extern const WINE_CONTEXT_INTERFACE *pCertInterface DECLSPEC_HIDDEN;
+extern const WINE_CONTEXT_INTERFACE *pCRLInterface DECLSPEC_HIDDEN;
+extern const WINE_CONTEXT_INTERFACE *pCTLInterface DECLSPEC_HIDDEN;
 
 typedef struct WINE_CRYPTCERTSTORE * (*StoreOpenFunc)(HCRYPTPROV hCryptProv,
  DWORD dwFlags, const void *pvPara);
 
-/* Called to enumerate the next context in a store. */
-typedef void * (*EnumFunc)(struct WINE_CRYPTCERTSTORE *store, void *pPrev);
-
-/* Called to add a context to a store.  If toReplace is not NULL,
- * context replaces toReplace in the store, and access checks should not be
- * performed.  Otherwise context is a new context, and it should only be
- * added if the store allows it.  If ppStoreContext is not NULL, the added
- * context should be returned in *ppStoreContext.
- */
-typedef BOOL (*AddFunc)(struct WINE_CRYPTCERTSTORE *store, void *context,
- void *toReplace, const void **ppStoreContext);
-
-typedef BOOL (*DeleteFunc)(struct WINE_CRYPTCERTSTORE *store, void *context);
-
 typedef struct _CONTEXT_FUNCS
 {
-    AddFunc    addContext;
-    EnumFunc   enumContext;
-    DeleteFunc deleteContext;
-} CONTEXT_FUNCS, *PCONTEXT_FUNCS;
+  /* Called to add a context to a store.  If toReplace is not NULL,
+   * context replaces toReplace in the store, and access checks should not be
+   * performed.  Otherwise context is a new context, and it should only be
+   * added if the store allows it.  If ppStoreContext is not NULL, the added
+   * context should be returned in *ppStoreContext.
+   */
+    BOOL (*addContext)(struct WINE_CRYPTCERTSTORE*,context_t*,context_t*,context_t**,BOOL);
+    context_t *(*enumContext)(struct WINE_CRYPTCERTSTORE *store, context_t *prev);
+    BOOL (*delete)(struct WINE_CRYPTCERTSTORE*,context_t*);
+} CONTEXT_FUNCS;
 
 typedef enum _CertStoreType {
     StoreTypeMem,
     StoreTypeCollection,
     StoreTypeProvider,
+    StoreTypeEmpty
 } CertStoreType;
 
-struct _CONTEXT_PROPERTY_LIST;
-typedef struct _CONTEXT_PROPERTY_LIST *PCONTEXT_PROPERTY_LIST;
-
 #define WINE_CRYPTCERTSTORE_MAGIC 0x74726563
 
 /* A cert store is polymorphic through the use of function pointers.  A type
@@ -277,49 +323,55 @@ typedef struct _CONTEXT_PROPERTY_LIST *PCONTEXT_PROPERTY_LIST;
  * - control is optional, but should be implemented by any store that supports
  *   persistence
  */
+
+typedef struct {
+    void (*addref)(struct WINE_CRYPTCERTSTORE*);
+    DWORD (*release)(struct WINE_CRYPTCERTSTORE*,DWORD);
+    void (*releaseContext)(struct WINE_CRYPTCERTSTORE*,context_t*);
+    BOOL (*control)(struct WINE_CRYPTCERTSTORE*,DWORD,DWORD,void const*);
+    CONTEXT_FUNCS certs;
+    CONTEXT_FUNCS crls;
+    CONTEXT_FUNCS ctls;
+} store_vtbl_t;
+
 typedef struct WINE_CRYPTCERTSTORE
 {
     DWORD                       dwMagic;
     LONG                        ref;
     DWORD                       dwOpenFlags;
     CertStoreType               type;
-    PFN_CERT_STORE_PROV_CLOSE   closeStore;
-    CONTEXT_FUNCS               certs;
-    CONTEXT_FUNCS               crls;
-    CONTEXT_FUNCS               ctls;
-    PFN_CERT_STORE_PROV_CONTROL control; /* optional */
-    PCONTEXT_PROPERTY_LIST      properties;
-} WINECRYPT_CERTSTORE, *PWINECRYPT_CERTSTORE;
+    const store_vtbl_t         *vtbl;
+    CONTEXT_PROPERTY_LIST      *properties;
+} WINECRYPT_CERTSTORE;
 
 void CRYPT_InitStore(WINECRYPT_CERTSTORE *store, DWORD dwFlags,
- CertStoreType type) DECLSPEC_HIDDEN;
-void CRYPT_FreeStore(PWINECRYPT_CERTSTORE store) DECLSPEC_HIDDEN;
+ CertStoreType type, const store_vtbl_t*) DECLSPEC_HIDDEN;
+void CRYPT_FreeStore(WINECRYPT_CERTSTORE *store) DECLSPEC_HIDDEN;
 BOOL WINAPI I_CertUpdateStore(HCERTSTORE store1, HCERTSTORE store2, DWORD unk0,
  DWORD unk1) DECLSPEC_HIDDEN;
 
-PWINECRYPT_CERTSTORE CRYPT_CollectionOpenStore(HCRYPTPROV hCryptProv,
+WINECRYPT_CERTSTORE *CRYPT_CollectionOpenStore(HCRYPTPROV hCryptProv,
  DWORD dwFlags, const void *pvPara) DECLSPEC_HIDDEN;
-PWINECRYPT_CERTSTORE CRYPT_ProvCreateStore(DWORD dwFlags,
PWINECRYPT_CERTSTORE memStore, const CERT_STORE_PROV_INFO *pProvInfo) DECLSPEC_HIDDEN;
-PWINECRYPT_CERTSTORE CRYPT_ProvOpenStore(LPCSTR lpszStoreProvider,
+WINECRYPT_CERTSTORE *CRYPT_ProvCreateStore(DWORD dwFlags,
WINECRYPT_CERTSTORE *memStore, const CERT_STORE_PROV_INFO *pProvInfo) DECLSPEC_HIDDEN;
+WINECRYPT_CERTSTORE *CRYPT_ProvOpenStore(LPCSTR lpszStoreProvider,
  DWORD dwEncodingType, HCRYPTPROV hCryptProv, DWORD dwFlags,
  const void *pvPara) DECLSPEC_HIDDEN;
-PWINECRYPT_CERTSTORE CRYPT_RegOpenStore(HCRYPTPROV hCryptProv, DWORD dwFlags,
+WINECRYPT_CERTSTORE *CRYPT_RegOpenStore(HCRYPTPROV hCryptProv, DWORD dwFlags,
  const void *pvPara) DECLSPEC_HIDDEN;
-PWINECRYPT_CERTSTORE CRYPT_FileOpenStore(HCRYPTPROV hCryptProv, DWORD dwFlags,
+WINECRYPT_CERTSTORE *CRYPT_FileOpenStore(HCRYPTPROV hCryptProv, DWORD dwFlags,
  const void *pvPara) DECLSPEC_HIDDEN;
-PWINECRYPT_CERTSTORE CRYPT_FileNameOpenStoreA(HCRYPTPROV hCryptProv,
+WINECRYPT_CERTSTORE *CRYPT_FileNameOpenStoreA(HCRYPTPROV hCryptProv,
  DWORD dwFlags, const void *pvPara) DECLSPEC_HIDDEN;
-PWINECRYPT_CERTSTORE CRYPT_FileNameOpenStoreW(HCRYPTPROV hCryptProv,
+WINECRYPT_CERTSTORE *CRYPT_FileNameOpenStoreW(HCRYPTPROV hCryptProv,
  DWORD dwFlags, const void *pvPara) DECLSPEC_HIDDEN;
-PWINECRYPT_CERTSTORE CRYPT_RootOpenStore(HCRYPTPROV hCryptProv, DWORD dwFlags) DECLSPEC_HIDDEN;
+WINECRYPT_CERTSTORE *CRYPT_RootOpenStore(HCRYPTPROV hCryptProv, DWORD dwFlags) DECLSPEC_HIDDEN;
 
 /* Allocates and initializes a certificate chain engine, but without creating
  * the root store.  Instead, it uses root, and assumes the caller has done any
  * checking necessary.
  */
-HCERTCHAINENGINE CRYPT_CreateChainEngine(HCERTSTORE root,
- PCERT_CHAIN_ENGINE_CONFIG pConfig) DECLSPEC_HIDDEN;
+HCERTCHAINENGINE CRYPT_CreateChainEngine(HCERTSTORE, DWORD, const CERT_CHAIN_ENGINE_CONFIG*) DECLSPEC_HIDDEN;
 
 /* Helper function for store reading functions and
  * CertAddSerializedElementToStore.  Returns a context of the appropriate type
@@ -365,89 +417,49 @@ DWORD cert_name_to_str_with_indent(DWORD dwCertEncodingType, DWORD indent,
  * which should be one of CERT_CONTEXT, CRL_CONTEXT, or CTL_CONTEXT.
  * Free with Context_Release.
  */
-void *Context_CreateDataContext(size_t contextSize) DECLSPEC_HIDDEN;
+context_t *Context_CreateDataContext(size_t contextSize, const context_vtbl_t *vtbl, struct WINE_CRYPTCERTSTORE*) DECLSPEC_HIDDEN;
 
-/* Creates a new link context with extra bytes.  The context refers to linked
+/* Creates a new link context.  The context refers to linked
  * rather than owning its own properties.  If addRef is TRUE (which ordinarily
  * it should be) linked is addref'd.
  * Free with Context_Release.
  */
-void *Context_CreateLinkContext(unsigned int contextSize, void *linked, unsigned int extra,
- BOOL addRef) DECLSPEC_HIDDEN;
-
-/* Returns a pointer to the extra bytes allocated with context, which must be
- * a link context.
- */
-void *Context_GetExtra(const void *context, size_t contextSize) DECLSPEC_HIDDEN;
-
-/* Gets the context linked to by context, which must be a link context. */
-void *Context_GetLinkedContext(void *context, size_t contextSize) DECLSPEC_HIDDEN;
+context_t *Context_CreateLinkContext(unsigned contextSize, context_t *linked, struct WINE_CRYPTCERTSTORE*) DECLSPEC_HIDDEN;
 
 /* Copies properties from fromContext to toContext. */
-void Context_CopyProperties(const void *to, const void *from,
- size_t contextSize) DECLSPEC_HIDDEN;
-
-/* Returns context's properties, or the linked context's properties if context
- * is a link context.
- */
-PCONTEXT_PROPERTY_LIST Context_GetProperties(const void *context, size_t contextSize) DECLSPEC_HIDDEN;
+void Context_CopyProperties(const void *to, const void *from) DECLSPEC_HIDDEN;
 
-void Context_AddRef(void *context, size_t contextSize) DECLSPEC_HIDDEN;
-
-typedef void (*ContextFreeFunc)(void *context);
-
-/* Decrements context's ref count.  If context is a link context, releases its
- * linked context as well.
- * If a data context has its ref count reach 0, calls dataContextFree on it.
- * Returns FALSE if the reference count is <= 0 when called.
- */
-BOOL Context_Release(void *context, size_t contextSize,
- ContextFreeFunc dataContextFree) DECLSPEC_HIDDEN;
+void Context_AddRef(context_t*) DECLSPEC_HIDDEN;
+void Context_Release(context_t *context) DECLSPEC_HIDDEN;
+void Context_Free(context_t*) DECLSPEC_HIDDEN;
 
 /**
  *  Context property list functions
  */
 
-PCONTEXT_PROPERTY_LIST ContextPropertyList_Create(void) DECLSPEC_HIDDEN;
+CONTEXT_PROPERTY_LIST *ContextPropertyList_Create(void) DECLSPEC_HIDDEN;
 
 /* Searches for the property with ID id in the context.  Returns TRUE if found,
  * and copies the property's length and a pointer to its data to blob.
  * Otherwise returns FALSE.
  */
-BOOL ContextPropertyList_FindProperty(PCONTEXT_PROPERTY_LIST list, DWORD id,
+BOOL ContextPropertyList_FindProperty(CONTEXT_PROPERTY_LIST *list, DWORD id,
  PCRYPT_DATA_BLOB blob) DECLSPEC_HIDDEN;
 
-BOOL ContextPropertyList_SetProperty(PCONTEXT_PROPERTY_LIST list, DWORD id,
+BOOL ContextPropertyList_SetProperty(CONTEXT_PROPERTY_LIST *list, DWORD id,
  const BYTE *pbData, size_t cbData) DECLSPEC_HIDDEN;
 
-void ContextPropertyList_RemoveProperty(PCONTEXT_PROPERTY_LIST list, DWORD id) DECLSPEC_HIDDEN;
+void ContextPropertyList_RemoveProperty(CONTEXT_PROPERTY_LIST *list, DWORD id) DECLSPEC_HIDDEN;
 
-DWORD ContextPropertyList_EnumPropIDs(PCONTEXT_PROPERTY_LIST list, DWORD id) DECLSPEC_HIDDEN;
+DWORD ContextPropertyList_EnumPropIDs(CONTEXT_PROPERTY_LIST *list, DWORD id) DECLSPEC_HIDDEN;
 
-void ContextPropertyList_Copy(PCONTEXT_PROPERTY_LIST to,
PCONTEXT_PROPERTY_LIST from) DECLSPEC_HIDDEN;
+void ContextPropertyList_Copy(CONTEXT_PROPERTY_LIST *to,
CONTEXT_PROPERTY_LIST *from) DECLSPEC_HIDDEN;
 
-void ContextPropertyList_Free(PCONTEXT_PROPERTY_LIST list) DECLSPEC_HIDDEN;
-
-/**
- *  Context list functions.  A context list is a simple list of link contexts.
- */
-struct ContextList;
-
-struct ContextList *ContextList_Create(
- PCWINE_CONTEXT_INTERFACE contextInterface, size_t contextSize) DECLSPEC_HIDDEN;
-
-void *ContextList_Add(struct ContextList *list, void *toLink, void *toReplace) DECLSPEC_HIDDEN;
-
-void *ContextList_Enum(struct ContextList *list, void *pPrev) DECLSPEC_HIDDEN;
-
-/* Removes a context from the list.  Returns TRUE if the context was removed,
- * or FALSE if not.  (The context may have been duplicated, so subsequent
- * removes have no effect.)
- */
-BOOL ContextList_Remove(struct ContextList *list, void *context) DECLSPEC_HIDDEN;
+void ContextPropertyList_Free(CONTEXT_PROPERTY_LIST *list) DECLSPEC_HIDDEN;
 
-void ContextList_Free(struct ContextList *list) DECLSPEC_HIDDEN;
+extern WINECRYPT_CERTSTORE empty_store;
+void init_empty_store(void) DECLSPEC_HIDDEN;
 
 /**
  *  Utilities.
index cff0c4b..ec2f0aa 100644 (file)
 
 WINE_DEFAULT_DEBUG_CHANNEL(crypt);
 
-#define CtlContext_CopyProperties(to, from) \
- Context_CopyProperties((to), (from), sizeof(CTL_CONTEXT))
+static void CTL_free(context_t *context)
+{
+    ctl_t *ctl = (ctl_t*)context;
+
+    CryptMsgClose(ctl->ctx.hCryptMsg);
+    CryptMemFree(ctl->ctx.pbCtlEncoded);
+    CryptMemFree(ctl->ctx.pbCtlContext);
+    LocalFree(ctl->ctx.pCtlInfo);
+}
+
+static context_t *CTL_clone(context_t *context, WINECRYPT_CERTSTORE *store, BOOL use_link)
+{
+    ctl_t *ctl;
+
+    if(!use_link) {
+        FIXME("Only links supported\n");
+        return NULL;
+    }
+
+    ctl = (ctl_t*)Context_CreateLinkContext(sizeof(CTL_CONTEXT), context, store);
+    if(!ctl)
+        return NULL;
+
+    ctl->ctx.hCertStore = store;
+    return &ctl->base;
+}
+
+static const context_vtbl_t ctl_vtbl = {
+    CTL_free,
+    CTL_clone
+};
 
 BOOL WINAPI CertAddCTLContextToStore(HCERTSTORE hCertStore,
  PCCTL_CONTEXT pCtlContext, DWORD dwAddDisposition,
  PCCTL_CONTEXT* ppStoreContext)
 {
-    PWINECRYPT_CERTSTORE store = hCertStore;
+    WINECRYPT_CERTSTORE *store = hCertStore;
     BOOL ret = TRUE;
     PCCTL_CONTEXT toAdd = NULL, existing = NULL;
 
@@ -83,7 +112,7 @@ BOOL WINAPI CertAddCTLContextToStore(HCERTSTORE hCertStore,
             if (newer < 0)
             {
                 toAdd = CertDuplicateCTLContext(pCtlContext);
-                CtlContext_CopyProperties(existing, pCtlContext);
+                Context_CopyProperties(existing, pCtlContext);
             }
             else
             {
@@ -101,12 +130,12 @@ BOOL WINAPI CertAddCTLContextToStore(HCERTSTORE hCertStore,
     case CERT_STORE_ADD_REPLACE_EXISTING_INHERIT_PROPERTIES:
         toAdd = CertDuplicateCTLContext(pCtlContext);
         if (existing)
-            CtlContext_CopyProperties(toAdd, existing);
+            Context_CopyProperties(toAdd, existing);
         break;
     case CERT_STORE_ADD_USE_EXISTING:
         if (existing)
         {
-            CtlContext_CopyProperties(existing, pCtlContext);
+            Context_CopyProperties(existing, pCtlContext);
             if (ppStoreContext)
                 *ppStoreContext = CertDuplicateCTLContext(existing);
         }
@@ -120,11 +149,16 @@ BOOL WINAPI CertAddCTLContextToStore(HCERTSTORE hCertStore,
 
     if (toAdd)
     {
-        if (store)
-            ret = store->ctls.addContext(store, (void *)toAdd,
-             (void *)existing, (const void **)ppStoreContext);
-        else if (ppStoreContext)
+        if (store) {
+            context_t *ret_ctx;
+
+            ret = store->vtbl->ctls.addContext(store, context_from_ptr(toAdd),
+             existing ? context_from_ptr(existing) : NULL, ppStoreContext ? &ret_ctx : NULL, TRUE);
+            if(ret && ppStoreContext)
+                *ppStoreContext = context_ptr(ret_ctx);
+        }else if (ppStoreContext) {
             *ppStoreContext = CertDuplicateCTLContext(toAdd);
+        }
         CertFreeCTLContext(toAdd);
     }
     CertFreeCTLContext(existing);
@@ -156,11 +190,10 @@ BOOL WINAPI CertAddEncodedCTLToStore(HCERTSTORE hCertStore,
     return ret;
 }
 
-PCCTL_CONTEXT WINAPI CertEnumCTLsInStore(HCERTSTORE hCertStore,
- PCCTL_CONTEXT pPrev)
+PCCTL_CONTEXT WINAPI CertEnumCTLsInStore(HCERTSTORE hCertStore, PCCTL_CONTEXT pPrev)
 {
+    ctl_t *prev = pPrev ? ctl_from_ptr(pPrev) : NULL, *ret;
     WINECRYPT_CERTSTORE *hcs = hCertStore;
-    PCCTL_CONTEXT ret;
 
     TRACE("(%p, %p)\n", hCertStore, pPrev);
     if (!hCertStore)
@@ -168,8 +201,8 @@ PCCTL_CONTEXT WINAPI CertEnumCTLsInStore(HCERTSTORE hCertStore,
     else if (hcs->dwMagic != WINE_CRYPTCERTSTORE_MAGIC)
         ret = NULL;
     else
-        ret = (PCCTL_CONTEXT)hcs->ctls.enumContext(hcs, (void *)pPrev);
-    return ret;
+        ret = (ctl_t*)hcs->vtbl->ctls.enumContext(hcs, prev ? &prev->base : NULL);
+    return ret ? &ret->ctx : NULL;
 }
 
 typedef BOOL (*CtlCompareFunc)(PCCTL_CONTEXT pCtlContext, DWORD dwType,
@@ -300,32 +333,30 @@ PCCTL_CONTEXT WINAPI CertFindCTLInStore(HCERTSTORE hCertStore,
 
 BOOL WINAPI CertDeleteCTLFromStore(PCCTL_CONTEXT pCtlContext)
 {
+    WINECRYPT_CERTSTORE *hcs;
+    ctl_t *ctl = ctl_from_ptr(pCtlContext);
     BOOL ret;
 
     TRACE("(%p)\n", pCtlContext);
 
     if (!pCtlContext)
-        ret = TRUE;
-    else if (!pCtlContext->hCertStore)
-        ret = CertFreeCTLContext(pCtlContext);
-    else
-    {
-        PWINECRYPT_CERTSTORE hcs = pCtlContext->hCertStore;
+        return TRUE;
 
-        if (hcs->dwMagic != WINE_CRYPTCERTSTORE_MAGIC)
-            ret = FALSE;
-        else
-            ret = hcs->ctls.deleteContext(hcs, (void *)pCtlContext);
-        if (ret)
-            ret = CertFreeCTLContext(pCtlContext);
-    }
+    hcs = pCtlContext->hCertStore;
+
+    if (hcs->dwMagic != WINE_CRYPTCERTSTORE_MAGIC)
+            return FALSE;
+
+    ret = hcs->vtbl->ctls.delete(hcs, &ctl->base);
+    if (ret)
+        ret = CertFreeCTLContext(pCtlContext);
     return ret;
 }
 
 PCCTL_CONTEXT WINAPI CertCreateCTLContext(DWORD dwMsgAndCertEncodingType,
  const BYTE *pbCtlEncoded, DWORD cbCtlEncoded)
 {
-    PCTL_CONTEXT ctl = NULL;
+    ctl_t *ctl = NULL;
     HCRYPTMSG msg;
     BOOL ret;
     BYTE *content = NULL;
@@ -398,7 +429,7 @@ PCCTL_CONTEXT WINAPI CertCreateCTLContext(DWORD dwMsgAndCertEncodingType,
              &ctlInfo, &size);
             if (ret)
             {
-                ctl = Context_CreateDataContext(sizeof(CTL_CONTEXT));
+                ctl = (ctl_t*)Context_CreateDataContext(sizeof(CTL_CONTEXT), &ctl_vtbl, &empty_store);
                 if (ctl)
                 {
                     BYTE *data = CryptMemAlloc(cbCtlEncoded);
@@ -406,15 +437,15 @@ PCCTL_CONTEXT WINAPI CertCreateCTLContext(DWORD dwMsgAndCertEncodingType,
                     if (data)
                     {
                         memcpy(data, pbCtlEncoded, cbCtlEncoded);
-                        ctl->dwMsgAndCertEncodingType =
+                        ctl->ctx.dwMsgAndCertEncodingType =
                          X509_ASN_ENCODING | PKCS_7_ASN_ENCODING;
-                        ctl->pbCtlEncoded             = data;
-                        ctl->cbCtlEncoded             = cbCtlEncoded;
-                        ctl->pCtlInfo                 = ctlInfo;
-                        ctl->hCertStore               = NULL;
-                        ctl->hCryptMsg                = msg;
-                        ctl->pbCtlContext             = content;
-                        ctl->cbCtlContext             = contentSize;
+                        ctl->ctx.pbCtlEncoded             = data;
+                        ctl->ctx.cbCtlEncoded             = cbCtlEncoded;
+                        ctl->ctx.pCtlInfo                 = ctlInfo;
+                        ctl->ctx.hCertStore               = &empty_store;
+                        ctl->ctx.hCryptMsg                = msg;
+                        ctl->ctx.pbCtlContext             = content;
+                        ctl->ctx.cbCtlContext             = contentSize;
                     }
                     else
                     {
@@ -439,65 +470,53 @@ PCCTL_CONTEXT WINAPI CertCreateCTLContext(DWORD dwMsgAndCertEncodingType,
 end:
     if (!ret)
     {
-        CertFreeCTLContext(ctl);
+        if(ctl)
+            Context_Release(&ctl->base);
         ctl = NULL;
         LocalFree(ctlInfo);
         CryptMemFree(content);
         CryptMsgClose(msg);
+        return NULL;
     }
-    return ctl;
+    return &ctl->ctx;
 }
 
 PCCTL_CONTEXT WINAPI CertDuplicateCTLContext(PCCTL_CONTEXT pCtlContext)
 {
     TRACE("(%p)\n", pCtlContext);
     if (pCtlContext)
-        Context_AddRef((void *)pCtlContext, sizeof(CTL_CONTEXT));
+        Context_AddRef(&ctl_from_ptr(pCtlContext)->base);
     return pCtlContext;
 }
 
-static void CTLDataContext_Free(void *context)
-{
-    PCTL_CONTEXT ctlContext = context;
-
-    CryptMsgClose(ctlContext->hCryptMsg);
-    CryptMemFree(ctlContext->pbCtlEncoded);
-    CryptMemFree(ctlContext->pbCtlContext);
-    LocalFree(ctlContext->pCtlInfo);
-}
-
 BOOL WINAPI CertFreeCTLContext(PCCTL_CONTEXT pCTLContext)
 {
-    BOOL ret = TRUE;
-
     TRACE("(%p)\n", pCTLContext);
 
     if (pCTLContext)
-        ret = Context_Release((void *)pCTLContext, sizeof(CTL_CONTEXT),
-         CTLDataContext_Free);
-    return ret;
+        Context_Release(&ctl_from_ptr(pCTLContext)->base);
+    return TRUE;
 }
 
 DWORD WINAPI CertEnumCTLContextProperties(PCCTL_CONTEXT pCTLContext,
  DWORD dwPropId)
 {
-    PCONTEXT_PROPERTY_LIST properties = Context_GetProperties(
-     pCTLContext, sizeof(CTL_CONTEXT));
+    ctl_t *ctl = ctl_from_ptr(pCTLContext);
     DWORD ret;
 
     TRACE("(%p, %d)\n", pCTLContext, dwPropId);
 
-    if (properties)
-        ret = ContextPropertyList_EnumPropIDs(properties, dwPropId);
+    if (ctl->base.properties)
+        ret = ContextPropertyList_EnumPropIDs(ctl->base.properties, dwPropId);
     else
         ret = 0;
     return ret;
 }
 
-static BOOL CTLContext_SetProperty(PCCTL_CONTEXT context, DWORD dwPropId,
+static BOOL CTLContext_SetProperty(ctl_t *ctl, DWORD dwPropId,
                                    DWORD dwFlags, const void *pvData);
 
-static BOOL CTLContext_GetHashProp(PCCTL_CONTEXT context, DWORD dwPropId,
+static BOOL CTLContext_GetHashProp(ctl_t *ctl, DWORD dwPropId,
  ALG_ID algID, const BYTE *toHash, DWORD toHashLen, void *pvData,
  DWORD *pcbData)
 {
@@ -507,23 +526,21 @@ static BOOL CTLContext_GetHashProp(PCCTL_CONTEXT context, DWORD dwPropId,
     {
         CRYPT_DATA_BLOB blob = { *pcbData, pvData };
 
-        ret = CTLContext_SetProperty(context, dwPropId, 0, &blob);
+        ret = CTLContext_SetProperty(ctl, dwPropId, 0, &blob);
     }
     return ret;
 }
 
-static BOOL CTLContext_GetProperty(PCCTL_CONTEXT context, DWORD dwPropId,
+static BOOL CTLContext_GetProperty(ctl_t *ctl, DWORD dwPropId,
                                    void *pvData, DWORD *pcbData)
 {
-    PCONTEXT_PROPERTY_LIST properties =
-     Context_GetProperties(context, sizeof(CTL_CONTEXT));
     BOOL ret;
     CRYPT_DATA_BLOB blob;
 
-    TRACE("(%p, %d, %p, %p)\n", context, dwPropId, pvData, pcbData);
+    TRACE("(%p, %d, %p, %p)\n", ctl, dwPropId, pvData, pcbData);
 
-    if (properties)
-        ret = ContextPropertyList_FindProperty(properties, dwPropId, &blob);
+    if (ctl->base.properties)
+        ret = ContextPropertyList_FindProperty(ctl->base.properties, dwPropId, &blob);
     else
         ret = FALSE;
     if (ret)
@@ -548,12 +565,12 @@ static BOOL CTLContext_GetProperty(PCCTL_CONTEXT context, DWORD dwPropId,
         switch (dwPropId)
         {
         case CERT_SHA1_HASH_PROP_ID:
-            ret = CTLContext_GetHashProp(context, dwPropId, CALG_SHA1,
-             context->pbCtlEncoded, context->cbCtlEncoded, pvData, pcbData);
+            ret = CTLContext_GetHashProp(ctl, dwPropId, CALG_SHA1,
+             ctl->ctx.pbCtlEncoded, ctl->ctx.cbCtlEncoded, pvData, pcbData);
             break;
         case CERT_MD5_HASH_PROP_ID:
-            ret = CTLContext_GetHashProp(context, dwPropId, CALG_MD5,
-             context->pbCtlEncoded, context->cbCtlEncoded, pvData, pcbData);
+            ret = CTLContext_GetHashProp(ctl, dwPropId, CALG_MD5,
+             ctl->ctx.pbCtlEncoded, ctl->ctx.cbCtlEncoded, pvData, pcbData);
             break;
         default:
             SetLastError(CRYPT_E_NOT_FOUND);
@@ -593,37 +610,28 @@ BOOL WINAPI CertGetCTLContextProperty(PCCTL_CONTEXT pCTLContext,
         }
         else
         {
-            if (pCTLContext->hCertStore)
-                ret = CertGetStoreProperty(pCTLContext->hCertStore, dwPropId,
-                 pvData, pcbData);
-            else
-            {
-                *(DWORD *)pvData = 0;
-                ret = TRUE;
-            }
+            ret = CertGetStoreProperty(pCTLContext->hCertStore, dwPropId, pvData, pcbData);
         }
         break;
     default:
-        ret = CTLContext_GetProperty(pCTLContext, dwPropId, pvData,
+        ret = CTLContext_GetProperty(ctl_from_ptr(pCTLContext), dwPropId, pvData,
          pcbData);
     }
     return ret;
 }
 
-static BOOL CTLContext_SetProperty(PCCTL_CONTEXT context, DWORD dwPropId,
+static BOOL CTLContext_SetProperty(ctl_t *ctl, DWORD dwPropId,
  DWORD dwFlags, const void *pvData)
 {
-    PCONTEXT_PROPERTY_LIST properties =
-     Context_GetProperties(context, sizeof(CTL_CONTEXT));
     BOOL ret;
 
-    TRACE("(%p, %d, %08x, %p)\n", context, dwPropId, dwFlags, pvData);
+    TRACE("(%p, %d, %08x, %p)\n", ctl, dwPropId, dwFlags, pvData);
 
-    if (!properties)
+    if (!ctl->base.properties)
         ret = FALSE;
     else if (!pvData)
     {
-        ContextPropertyList_RemoveProperty(properties, dwPropId);
+        ContextPropertyList_RemoveProperty(ctl->base.properties, dwPropId);
         ret = TRUE;
     }
     else
@@ -650,12 +658,12 @@ static BOOL CTLContext_SetProperty(PCCTL_CONTEXT context, DWORD dwPropId,
         {
             PCRYPT_DATA_BLOB blob = (PCRYPT_DATA_BLOB)pvData;
 
-            ret = ContextPropertyList_SetProperty(properties, dwPropId,
+            ret = ContextPropertyList_SetProperty(ctl->base.properties, dwPropId,
              blob->pbData, blob->cbData);
             break;
         }
         case CERT_DATE_STAMP_PROP_ID:
-            ret = ContextPropertyList_SetProperty(properties, dwPropId,
+            ret = ContextPropertyList_SetProperty(ctl->base.properties, dwPropId,
              pvData, sizeof(FILETIME));
             break;
         default:
@@ -687,7 +695,7 @@ BOOL WINAPI CertSetCTLContextProperty(PCCTL_CONTEXT pCTLContext,
         SetLastError(E_INVALIDARG);
         return FALSE;
     }
-    ret = CTLContext_SetProperty(pCTLContext, dwPropId, dwFlags, pvData);
+    ret = CTLContext_SetProperty(ctl_from_ptr(pCTLContext), dwPropId, dwFlags, pvData);
     TRACE("returning %d\n", ret);
     return ret;
 }
index 16ff330..d6b61a8 100644 (file)
@@ -2060,7 +2060,7 @@ static BOOL CRYPT_AsnEncodeNumericString(const CERT_NAME_VALUE *value,
     return ret;
 }
 
-static inline int isprintableW(WCHAR wc)
+static inline BOOL isprintableW(WCHAR wc)
 {
     return isalnumW(wc) || isspaceW(wc) || wc == '\'' || wc == '(' ||
      wc == ')' || wc == '+' || wc == ',' || wc == '-' || wc == '.' ||
index b05751b..f3e618f 100644 (file)
@@ -27,11 +27,11 @@ typedef struct _WINE_FILESTOREINFO
     HANDLE     file;
     DWORD      type;
     BOOL       dirty;
-} WINE_FILESTOREINFO, *PWINE_FILESTOREINFO;
+} WINE_FILESTOREINFO;
 
 static void WINAPI CRYPT_FileCloseStore(HCERTSTORE hCertStore, DWORD dwFlags)
 {
-    PWINE_FILESTOREINFO store = hCertStore;
+    WINE_FILESTOREINFO *store = hCertStore;
 
     TRACE("(%p, %08x)\n", store, dwFlags);
     if (store->dirty)
@@ -44,7 +44,7 @@ static void WINAPI CRYPT_FileCloseStore(HCERTSTORE hCertStore, DWORD dwFlags)
 static BOOL WINAPI CRYPT_FileWriteCert(HCERTSTORE hCertStore,
  PCCERT_CONTEXT cert, DWORD dwFlags)
 {
-    PWINE_FILESTOREINFO store = hCertStore;
+    WINE_FILESTOREINFO *store = hCertStore;
 
     TRACE("(%p, %p, %d)\n", hCertStore, cert, dwFlags);
     store->dirty = TRUE;
@@ -54,7 +54,7 @@ static BOOL WINAPI CRYPT_FileWriteCert(HCERTSTORE hCertStore,
 static BOOL WINAPI CRYPT_FileDeleteCert(HCERTSTORE hCertStore,
  PCCERT_CONTEXT pCertContext, DWORD dwFlags)
 {
-    PWINE_FILESTOREINFO store = hCertStore;
+    WINE_FILESTOREINFO *store = hCertStore;
 
     TRACE("(%p, %p, %08x)\n", hCertStore, pCertContext, dwFlags);
     store->dirty = TRUE;
@@ -64,7 +64,7 @@ static BOOL WINAPI CRYPT_FileDeleteCert(HCERTSTORE hCertStore,
 static BOOL WINAPI CRYPT_FileWriteCRL(HCERTSTORE hCertStore,
  PCCRL_CONTEXT crl, DWORD dwFlags)
 {
-    PWINE_FILESTOREINFO store = hCertStore;
+    WINE_FILESTOREINFO *store = hCertStore;
 
     TRACE("(%p, %p, %d)\n", hCertStore, crl, dwFlags);
     store->dirty = TRUE;
@@ -74,7 +74,7 @@ static BOOL WINAPI CRYPT_FileWriteCRL(HCERTSTORE hCertStore,
 static BOOL WINAPI CRYPT_FileDeleteCRL(HCERTSTORE hCertStore,
  PCCRL_CONTEXT pCrlContext, DWORD dwFlags)
 {
-    PWINE_FILESTOREINFO store = hCertStore;
+    WINE_FILESTOREINFO *store = hCertStore;
 
     TRACE("(%p, %p, %08x)\n", hCertStore, pCrlContext, dwFlags);
     store->dirty = TRUE;
@@ -84,7 +84,7 @@ static BOOL WINAPI CRYPT_FileDeleteCRL(HCERTSTORE hCertStore,
 static BOOL WINAPI CRYPT_FileWriteCTL(HCERTSTORE hCertStore,
  PCCTL_CONTEXT ctl, DWORD dwFlags)
 {
-    PWINE_FILESTOREINFO store = hCertStore;
+    WINE_FILESTOREINFO *store = hCertStore;
 
     TRACE("(%p, %p, %d)\n", hCertStore, ctl, dwFlags);
     store->dirty = TRUE;
@@ -94,7 +94,7 @@ static BOOL WINAPI CRYPT_FileWriteCTL(HCERTSTORE hCertStore,
 static BOOL WINAPI CRYPT_FileDeleteCTL(HCERTSTORE hCertStore,
  PCCTL_CONTEXT pCtlContext, DWORD dwFlags)
 {
-    PWINE_FILESTOREINFO store = hCertStore;
+    WINE_FILESTOREINFO *store = hCertStore;
 
     TRACE("(%p, %p, %08x)\n", hCertStore, pCtlContext, dwFlags);
     store->dirty = TRUE;
@@ -113,8 +113,11 @@ static BOOL CRYPT_ReadBlobFromFile(HANDLE file, PCERT_BLOB blob)
         {
             DWORD read;
 
-            ret = ReadFile(file, blob->pbData, blob->cbData, &read, NULL);
+            ret = ReadFile(file, blob->pbData, blob->cbData, &read, NULL) && read == blob->cbData;
+            if (!ret) CryptMemFree(blob->pbData);
         }
+        else
+            ret = FALSE;
     }
     return ret;
 }
@@ -122,7 +125,7 @@ static BOOL CRYPT_ReadBlobFromFile(HANDLE file, PCERT_BLOB blob)
 static BOOL WINAPI CRYPT_FileControl(HCERTSTORE hCertStore, DWORD dwFlags,
  DWORD dwCtrlType, void const *pvCtrlPara)
 {
-    PWINE_FILESTOREINFO store = hCertStore;
+    WINE_FILESTOREINFO *store = hCertStore;
     BOOL ret;
 
     TRACE("(%p, %08x, %d, %p)\n", hCertStore, dwFlags, dwCtrlType,
@@ -206,11 +209,11 @@ static void *fileProvFuncs[] = {
     CRYPT_FileControl,
 };
 
-static PWINECRYPT_CERTSTORE CRYPT_CreateFileStore(DWORD dwFlags,
+static WINECRYPT_CERTSTORE *CRYPT_CreateFileStore(DWORD dwFlags,
  HCERTSTORE memStore, HANDLE file, DWORD type)
 {
-    PWINECRYPT_CERTSTORE store = NULL;
-    PWINE_FILESTOREINFO info = CryptMemAlloc(sizeof(WINE_FILESTOREINFO));
+    WINECRYPT_CERTSTORE *store = NULL;
+    WINE_FILESTOREINFO *info = CryptMemAlloc(sizeof(WINE_FILESTOREINFO));
 
     if (info)
     {
@@ -231,10 +234,10 @@ static PWINECRYPT_CERTSTORE CRYPT_CreateFileStore(DWORD dwFlags,
     return store;
 }
 
-PWINECRYPT_CERTSTORE CRYPT_FileOpenStore(HCRYPTPROV hCryptProv, DWORD dwFlags,
+WINECRYPT_CERTSTORE *CRYPT_FileOpenStore(HCRYPTPROV hCryptProv, DWORD dwFlags,
  const void *pvPara)
 {
-    PWINECRYPT_CERTSTORE store = NULL;
+    WINECRYPT_CERTSTORE *store = NULL;
     HANDLE file = (HANDLE)pvPara;
 
     TRACE("(%ld, %08x, %p)\n", hCryptProv, dwFlags, pvPara);
@@ -281,7 +284,7 @@ PWINECRYPT_CERTSTORE CRYPT_FileOpenStore(HCRYPTPROV hCryptProv, DWORD dwFlags,
     return store;
 }
 
-PWINECRYPT_CERTSTORE CRYPT_FileNameOpenStoreW(HCRYPTPROV hCryptProv,
+WINECRYPT_CERTSTORE *CRYPT_FileNameOpenStoreW(HCRYPTPROV hCryptProv,
  DWORD dwFlags, const void *pvPara)
 {
     HCERTSTORE store = 0;
@@ -372,11 +375,11 @@ PWINECRYPT_CERTSTORE CRYPT_FileNameOpenStoreW(HCRYPTPROV hCryptProv,
     return store;
 }
 
-PWINECRYPT_CERTSTORE CRYPT_FileNameOpenStoreA(HCRYPTPROV hCryptProv,
+WINECRYPT_CERTSTORE *CRYPT_FileNameOpenStoreA(HCRYPTPROV hCryptProv,
  DWORD dwFlags, const void *pvPara)
 {
     int len;
-    PWINECRYPT_CERTSTORE ret = NULL;
+    WINECRYPT_CERTSTORE *ret = NULL;
 
     TRACE("(%ld, %08x, %s)\n", hCryptProv, dwFlags,
      debugstr_a(pvPara));
index f164aeb..776396e 100644 (file)
@@ -33,6 +33,7 @@ BOOL WINAPI DllMain(HINSTANCE hInst, DWORD fdwReason, PVOID pvReserved)
         case DLL_PROCESS_ATTACH:
             hInstance = hInst;
             DisableThreadLibraryCalls(hInst);
+            init_empty_store();
             crypt_oid_init();
             break;
         case DLL_PROCESS_DETACH:
index 2b6e938..35bbb95 100644 (file)
@@ -591,20 +591,20 @@ typedef struct _CMSG_SIGNER_ENCODE_INFO_WITH_CMS
     CERT_ID                    SignerId;
     CRYPT_ALGORITHM_IDENTIFIER HashEncryptionAlgorithm;
     void                      *pvHashEncryptionAuxInfo;
-} CMSG_SIGNER_ENCODE_INFO_WITH_CMS, *PCMSG_SIGNER_ENCODE_INFO_WITH_CMS;
+} CMSG_SIGNER_ENCODE_INFO_WITH_CMS;
 
 typedef struct _CMSG_SIGNED_ENCODE_INFO_WITH_CMS
 {
     DWORD                             cbSize;
     DWORD                             cSigners;
-    PCMSG_SIGNER_ENCODE_INFO_WITH_CMS rgSigners;
+    CMSG_SIGNER_ENCODE_INFO_WITH_CMS *rgSigners;
     DWORD                             cCertEncoded;
     PCERT_BLOB                        rgCertEncoded;
     DWORD                             cCrlEncoded;
     PCRL_BLOB                         rgCrlEncoded;
     DWORD                             cAttrCertEncoded;
     PCERT_BLOB                        rgAttrCertEncoded;
-} CMSG_SIGNED_ENCODE_INFO_WITH_CMS, *PCMSG_SIGNED_ENCODE_INFO_WITH_CMS;
+} CMSG_SIGNED_ENCODE_INFO_WITH_CMS;
 
 static BOOL CRYPT_IsValidSigner(const CMSG_SIGNER_ENCODE_INFO_WITH_CMS *signer)
 {
@@ -1462,7 +1462,7 @@ typedef struct _CMSG_ENVELOPED_ENCODE_INFO_WITH_CMS
     PCERT_BLOB                  rgAttrCertEncoded;
     DWORD                       cUnprotectedAttr;
     PCRYPT_ATTRIBUTE            rgUnprotectedAttr;
-} CMSG_ENVELOPED_ENCODE_INFO_WITH_CMS, *PCMSG_ENVELOPED_ENCODE_INFO_WITH_CMS;
+} CMSG_ENVELOPED_ENCODE_INFO_WITH_CMS;
 
 typedef struct _CEnvelopedEncodeMsg
 {
@@ -2059,7 +2059,7 @@ typedef struct _CDecodeMsg
     } u;
     CRYPT_DATA_BLOB        msg_data;
     CRYPT_DATA_BLOB        detached_data;
-    PCONTEXT_PROPERTY_LIST properties;
+    CONTEXT_PROPERTY_LIST *properties;
 } CDecodeMsg;
 
 static void CDecodeMsg_Close(HCRYPTMSG hCryptMsg)
index ce0f02c..78dea19 100644 (file)
@@ -44,8 +44,11 @@ static BOOL CRYPT_ReadBlobFromFile(LPCWSTR fileName, PCERT_BLOB blob)
             {
                 DWORD read;
 
-                ret = ReadFile(file, blob->pbData, blob->cbData, &read, NULL);
+                ret = ReadFile(file, blob->pbData, blob->cbData, &read, NULL) && read == blob->cbData;
+                if (!ret) CryptMemFree(blob->pbData);
             }
+            else
+                ret = FALSE;
         }
         CloseHandle(file);
     }
@@ -263,12 +266,15 @@ static BOOL CRYPT_QuerySerializedContextObject(DWORD dwObjectType,
             *phCertStore = CertDuplicateStore(
              *(HCERTSTORE *)((const BYTE *)context + certStoreOffset));
         if (ppvContext)
-            *ppvContext = contextInterface->duplicate(context);
+        {
+            *ppvContext = context;
+            Context_AddRef(context_from_ptr(context));
+        }
     }
 
 end:
     if (contextInterface && context)
-        contextInterface->free(context);
+        Context_Release(context_from_ptr(context));
     if (blob == &fileBlob)
         CryptMemFree(blob->pbData);
     TRACE("returning %d\n", ret);
index a417430..01e05d9 100644 (file)
@@ -1093,6 +1093,7 @@ static const WCHAR SpcFinancialCriteria[] = { 'S','p','c','F','i','n','a','n','c
 static const WCHAR SpcMinimalCriteria[] = { 'S','p','c','M','i','n','i','m','a','l','C','r','i','t','e','r','i','a',0 };
 static const WCHAR Email[] = { 'E','m','a','i','l',0 };
 static const WCHAR GN[] = { 'G','N',0 };
+static const WCHAR SERIALNUMBER[] = { 'S','E','R','I','A','L','N','U','M','B','E','R',0 };
 
 static const DWORD noNullFlag = CRYPT_OID_NO_NULL_ALGORITHM_PARA_FLAG;
 static const DWORD mosaicFlags = CRYPT_OID_INHIBIT_SIGNATURE_FORMAT_FLAG |
@@ -1212,6 +1213,7 @@ static const struct OIDInfoConstructor {
  { 5, szOID_TELEPHONE_NUMBER,         0, Phone, &printableStringBlob },
  { 5, szOID_X21_ADDRESS,              0, X21Address, &numericStringBlob },
  { 5, szOID_DN_QUALIFIER,             0, dnQualifier, NULL },
+ { 5, szOID_DEVICE_SERIAL_NUMBER,     0, SERIALNUMBER, NULL },
 
  { 6, szOID_AUTHORITY_KEY_IDENTIFIER2, 0, (LPCWSTR)IDS_AUTHORITY_KEY_ID, NULL },
  { 6, szOID_AUTHORITY_KEY_IDENTIFIER, 0, (LPCWSTR)IDS_AUTHORITY_KEY_ID, NULL },
index 2d021b2..ac84cbe 100644 (file)
 
 WINE_DEFAULT_DEBUG_CHANNEL(crypt);
 
-typedef struct _CONTEXT_PROPERTY_LIST
+struct _CONTEXT_PROPERTY_LIST
 {
     CRITICAL_SECTION cs;
     struct list      properties;
-} CONTEXT_PROPERTY_LIST;
+};
 
 typedef struct _CONTEXT_PROPERTY
 {
@@ -32,11 +32,11 @@ typedef struct _CONTEXT_PROPERTY
     DWORD       cbData;
     LPBYTE      pbData;
     struct list entry;
-} CONTEXT_PROPERTY, *PCONTEXT_PROPERTY;
+} CONTEXT_PROPERTY;
 
-PCONTEXT_PROPERTY_LIST ContextPropertyList_Create(void)
+CONTEXT_PROPERTY_LIST *ContextPropertyList_Create(void)
 {
-    PCONTEXT_PROPERTY_LIST list = CryptMemAlloc(sizeof(CONTEXT_PROPERTY_LIST));
+    CONTEXT_PROPERTY_LIST *list = CryptMemAlloc(sizeof(CONTEXT_PROPERTY_LIST));
 
     if (list)
     {
@@ -47,9 +47,9 @@ PCONTEXT_PROPERTY_LIST ContextPropertyList_Create(void)
     return list;
 }
 
-void ContextPropertyList_Free(PCONTEXT_PROPERTY_LIST list)
+void ContextPropertyList_Free(CONTEXT_PROPERTY_LIST *list)
 {
-    PCONTEXT_PROPERTY prop, next;
+    CONTEXT_PROPERTY *prop, *next;
 
     LIST_FOR_EACH_ENTRY_SAFE(prop, next, &list->properties, CONTEXT_PROPERTY,
      entry)
@@ -63,10 +63,10 @@ void ContextPropertyList_Free(PCONTEXT_PROPERTY_LIST list)
     CryptMemFree(list);
 }
 
-BOOL ContextPropertyList_FindProperty(PCONTEXT_PROPERTY_LIST list, DWORD id,
+BOOL ContextPropertyList_FindProperty(CONTEXT_PROPERTY_LIST *list, DWORD id,
  PCRYPT_DATA_BLOB blob)
 {
-    PCONTEXT_PROPERTY prop;
+    CONTEXT_PROPERTY *prop;
     BOOL ret = FALSE;
 
     TRACE("(%p, %d, %p)\n", list, id, blob);
@@ -86,7 +86,7 @@ BOOL ContextPropertyList_FindProperty(PCONTEXT_PROPERTY_LIST list, DWORD id,
     return ret;
 }
 
-BOOL ContextPropertyList_SetProperty(PCONTEXT_PROPERTY_LIST list, DWORD id,
+BOOL ContextPropertyList_SetProperty(CONTEXT_PROPERTY_LIST *list, DWORD id,
  const BYTE *pbData, size_t cbData)
 {
     LPBYTE data;
@@ -102,7 +102,7 @@ BOOL ContextPropertyList_SetProperty(PCONTEXT_PROPERTY_LIST list, DWORD id,
         data = NULL;
     if (!cbData || data)
     {
-        PCONTEXT_PROPERTY prop;
+        CONTEXT_PROPERTY *prop;
         BOOL found = FALSE;
 
         EnterCriticalSection(&list->cs);
@@ -140,9 +140,9 @@ BOOL ContextPropertyList_SetProperty(PCONTEXT_PROPERTY_LIST list, DWORD id,
     return ret;
 }
 
-void ContextPropertyList_RemoveProperty(PCONTEXT_PROPERTY_LIST list, DWORD id)
+void ContextPropertyList_RemoveProperty(CONTEXT_PROPERTY_LIST *list, DWORD id)
 {
-    PCONTEXT_PROPERTY prop, next;
+    CONTEXT_PROPERTY *prop, *next;
 
     EnterCriticalSection(&list->cs);
     LIST_FOR_EACH_ENTRY_SAFE(prop, next, &list->properties, CONTEXT_PROPERTY,
@@ -162,19 +162,22 @@ void ContextPropertyList_RemoveProperty(PCONTEXT_PROPERTY_LIST list, DWORD id)
 /* Since the properties are stored in a list, this is a tad inefficient
  * (O(n^2)) since I have to find the previous position every time.
  */
-DWORD ContextPropertyList_EnumPropIDs(PCONTEXT_PROPERTY_LIST list, DWORD id)
+DWORD ContextPropertyList_EnumPropIDs(CONTEXT_PROPERTY_LIST *list, DWORD id)
 {
     DWORD ret;
 
     EnterCriticalSection(&list->cs);
     if (id)
     {
-        PCONTEXT_PROPERTY cursor = NULL;
+        CONTEXT_PROPERTY *cursor = NULL, *prop;
 
-        LIST_FOR_EACH_ENTRY(cursor, &list->properties, CONTEXT_PROPERTY, entry)
+        LIST_FOR_EACH_ENTRY(prop, &list->properties, CONTEXT_PROPERTY, entry)
         {
-            if (cursor->propID == id)
+            if (prop->propID == id)
+            {
+                cursor = prop;
                 break;
+            }
         }
         if (cursor)
         {
@@ -196,10 +199,9 @@ DWORD ContextPropertyList_EnumPropIDs(PCONTEXT_PROPERTY_LIST list, DWORD id)
     return ret;
 }
 
-void ContextPropertyList_Copy(PCONTEXT_PROPERTY_LIST to,
- PCONTEXT_PROPERTY_LIST from)
+void ContextPropertyList_Copy(CONTEXT_PROPERTY_LIST *to, CONTEXT_PROPERTY_LIST *from)
 {
-    PCONTEXT_PROPERTY prop;
+    CONTEXT_PROPERTY *prop;
 
     EnterCriticalSection(&from->cs);
     LIST_FOR_EACH_ENTRY(prop, &from->properties, CONTEXT_PROPERTY, entry)
index 5968ac1..640ea62 100644 (file)
@@ -24,7 +24,7 @@ typedef struct _WINE_PROVIDERSTORE
 {
     WINECRYPT_CERTSTORE             hdr;
     DWORD                           dwStoreProvFlags;
-    PWINECRYPT_CERTSTORE            memStore;
+    WINECRYPT_CERTSTORE            *memStore;
     HCERTSTOREPROV                  hStoreProv;
     PFN_CERT_STORE_PROV_CLOSE       provCloseStore;
     PFN_CERT_STORE_PROV_WRITE_CERT  provWriteCert;
@@ -34,91 +34,112 @@ typedef struct _WINE_PROVIDERSTORE
     PFN_CERT_STORE_PROV_WRITE_CTL   provWriteCtl;
     PFN_CERT_STORE_PROV_DELETE_CTL  provDeleteCtl;
     PFN_CERT_STORE_PROV_CONTROL     provControl;
-} WINE_PROVIDERSTORE, *PWINE_PROVIDERSTORE;
+} WINE_PROVIDERSTORE;
 
-static void WINAPI CRYPT_ProvCloseStore(HCERTSTORE hCertStore, DWORD dwFlags)
+static void ProvStore_addref(WINECRYPT_CERTSTORE *store)
 {
-    PWINE_PROVIDERSTORE store = hCertStore;
+    LONG ref = InterlockedIncrement(&store->ref);
+    TRACE("ref = %d\n", ref);
+}
+
+static DWORD ProvStore_release(WINECRYPT_CERTSTORE *cert_store, DWORD flags)
+{
+    WINE_PROVIDERSTORE *store = (WINE_PROVIDERSTORE*)cert_store;
+    LONG ref;
+
+    if(flags)
+        FIXME("Unimplemented flags %x\n", flags);
 
-    TRACE("(%p, %08x)\n", store, dwFlags);
+    ref = InterlockedDecrement(&store->hdr.ref);
+    TRACE("(%p) ref=%d\n", store, ref);
+
+    if(ref)
+        return ERROR_SUCCESS;
 
     if (store->provCloseStore)
-        store->provCloseStore(store->hStoreProv, dwFlags);
+        store->provCloseStore(store->hStoreProv, flags);
     if (!(store->dwStoreProvFlags & CERT_STORE_PROV_EXTERNAL_FLAG))
-        CertCloseStore(store->memStore, dwFlags);
-    CRYPT_FreeStore((PWINECRYPT_CERTSTORE)store);
+        store->memStore->vtbl->release(store->memStore, flags);
+    CRYPT_FreeStore(&store->hdr);
+    return ERROR_SUCCESS;
+}
+
+static void ProvStore_releaseContext(WINECRYPT_CERTSTORE *store, context_t *context)
+{
+    /* As long as we don't have contexts properly stored (and hack around hCertStore
+       in add* and enum* functions), this function should never be called. */
+    assert(0);
 }
 
-static BOOL CRYPT_ProvAddCert(PWINECRYPT_CERTSTORE store, void *cert,
void *toReplace, const void **ppStoreContext)
+static BOOL ProvStore_addCert(WINECRYPT_CERTSTORE *store, context_t *cert,
context_t *toReplace, context_t **ppStoreContext, BOOL use_link)
 {
-    PWINE_PROVIDERSTORE ps = (PWINE_PROVIDERSTORE)store;
+    WINE_PROVIDERSTORE *ps = (WINE_PROVIDERSTORE*)store;
     BOOL ret;
 
     TRACE("(%p, %p, %p, %p)\n", store, cert, toReplace, ppStoreContext);
 
     if (toReplace)
-        ret = ps->memStore->certs.addContext(ps->memStore, cert, toReplace,
-         ppStoreContext);
+        ret = ps->memStore->vtbl->certs.addContext(ps->memStore, cert, toReplace,
+         ppStoreContext, TRUE);
     else
     {
         ret = TRUE;
         if (ps->provWriteCert)
-            ret = ps->provWriteCert(ps->hStoreProv, cert,
-             CERT_STORE_PROV_WRITE_ADD_FLAG);
+            ret = ps->provWriteCert(ps->hStoreProv, context_ptr(cert), CERT_STORE_PROV_WRITE_ADD_FLAG);
         if (ret)
-            ret = ps->memStore->certs.addContext(ps->memStore, cert, NULL,
-             ppStoreContext);
+            ret = ps->memStore->vtbl->certs.addContext(ps->memStore, cert, NULL,
+             ppStoreContext, TRUE);
     }
     /* dirty trick: replace the returned context's hCertStore with
      * store.
      */
     if (ret && ppStoreContext)
-        (*(PCERT_CONTEXT *)ppStoreContext)->hCertStore = store;
+        (*(cert_t**)ppStoreContext)->ctx.hCertStore = store;
     return ret;
 }
 
-static void *CRYPT_ProvEnumCert(PWINECRYPT_CERTSTORE store, void *pPrev)
+static context_t *ProvStore_enumCert(WINECRYPT_CERTSTORE *store, context_t *prev)
 {
-    PWINE_PROVIDERSTORE ps = (PWINE_PROVIDERSTORE)store;
-    void *ret;
+    WINE_PROVIDERSTORE *ps = (WINE_PROVIDERSTORE*)store;
+    cert_t *ret;
 
-    ret = ps->memStore->certs.enumContext(ps->memStore, pPrev);
-    if (ret)
-    {
-        /* same dirty trick: replace the returned context's hCertStore with
-         * store.
-         */
-        ((PCERT_CONTEXT)ret)->hCertStore = store;
-    }
-    return ret;
+    ret = (cert_t*)ps->memStore->vtbl->certs.enumContext(ps->memStore, prev);
+    if (!ret)
+        return NULL;
+
+    /* same dirty trick: replace the returned context's hCertStore with
+     * store.
+     */
+    ret->ctx.hCertStore = store;
+    return &ret->base;
 }
 
-static BOOL CRYPT_ProvDeleteCert(PWINECRYPT_CERTSTORE store, void *cert)
+static BOOL ProvStore_deleteCert(WINECRYPT_CERTSTORE *store, context_t *context)
 {
-    PWINE_PROVIDERSTORE ps = (PWINE_PROVIDERSTORE)store;
+    WINE_PROVIDERSTORE *ps = (WINE_PROVIDERSTORE*)store;
     BOOL ret = TRUE;
 
-    TRACE("(%p, %p)\n", store, cert);
+    TRACE("(%p, %p)\n", store, context);
 
     if (ps->provDeleteCert)
-        ret = ps->provDeleteCert(ps->hStoreProv, cert, 0);
+        ret = ps->provDeleteCert(ps->hStoreProv, context_ptr(context), 0);
     if (ret)
-        ret = ps->memStore->certs.deleteContext(ps->memStore, cert);
+        ret = ps->memStore->vtbl->certs.delete(ps->memStore, context);
     return ret;
 }
 
-static BOOL CRYPT_ProvAddCRL(PWINECRYPT_CERTSTORE store, void *crl,
void *toReplace, const void **ppStoreContext)
+static BOOL ProvStore_addCRL(WINECRYPT_CERTSTORE *store, context_t *crl,
context_t *toReplace, context_t **ppStoreContext, BOOL use_link)
 {
-    PWINE_PROVIDERSTORE ps = (PWINE_PROVIDERSTORE)store;
+    WINE_PROVIDERSTORE *ps = (WINE_PROVIDERSTORE*)store;
     BOOL ret;
 
     TRACE("(%p, %p, %p, %p)\n", store, crl, toReplace, ppStoreContext);
 
     if (toReplace)
-        ret = ps->memStore->crls.addContext(ps->memStore, crl, toReplace,
-         ppStoreContext);
+        ret = ps->memStore->vtbl->crls.addContext(ps->memStore, crl, toReplace,
+         ppStoreContext, TRUE);
     else
     {
         if (ps->hdr.dwOpenFlags & CERT_STORE_READONLY_FLAG)
@@ -130,62 +151,62 @@ static BOOL CRYPT_ProvAddCRL(PWINECRYPT_CERTSTORE store, void *crl,
         {
             ret = TRUE;
             if (ps->provWriteCrl)
-                ret = ps->provWriteCrl(ps->hStoreProv, crl,
+                ret = ps->provWriteCrl(ps->hStoreProv, context_ptr(crl),
                  CERT_STORE_PROV_WRITE_ADD_FLAG);
             if (ret)
-                ret = ps->memStore->crls.addContext(ps->memStore, crl, NULL,
-                 ppStoreContext);
+                ret = ps->memStore->vtbl->crls.addContext(ps->memStore, crl, NULL,
+                 ppStoreContext, TRUE);
         }
     }
     /* dirty trick: replace the returned context's hCertStore with
      * store.
      */
     if (ret && ppStoreContext)
-        (*(PCRL_CONTEXT *)ppStoreContext)->hCertStore = store;
+        (*(crl_t**)ppStoreContext)->ctx.hCertStore = store;
     return ret;
 }
 
-static void *CRYPT_ProvEnumCRL(PWINECRYPT_CERTSTORE store, void *pPrev)
+static context_t *ProvStore_enumCRL(WINECRYPT_CERTSTORE *store, context_t *prev)
 {
-    PWINE_PROVIDERSTORE ps = (PWINE_PROVIDERSTORE)store;
-    void *ret;
+    WINE_PROVIDERSTORE *ps = (WINE_PROVIDERSTORE*)store;
+    crl_t *ret;
 
-    ret = ps->memStore->crls.enumContext(ps->memStore, pPrev);
-    if (ret)
-    {
-        /* same dirty trick: replace the returned context's hCertStore with
-         * store.
-         */
-        ((PCRL_CONTEXT)ret)->hCertStore = store;
-    }
-    return ret;
+    ret = (crl_t*)ps->memStore->vtbl->crls.enumContext(ps->memStore, prev);
+    if (!ret)
+        return NULL;
+
+    /* same dirty trick: replace the returned context's hCertStore with
+     * store.
+     */
+    ret->ctx.hCertStore = store;
+    return &ret->base;
 }
 
-static BOOL CRYPT_ProvDeleteCRL(PWINECRYPT_CERTSTORE store, void *crl)
+static BOOL ProvStore_deleteCRL(WINECRYPT_CERTSTORE *store, context_t *crl)
 {
-    PWINE_PROVIDERSTORE ps = (PWINE_PROVIDERSTORE)store;
+    WINE_PROVIDERSTORE *ps = (WINE_PROVIDERSTORE*)store;
     BOOL ret = TRUE;
 
     TRACE("(%p, %p)\n", store, crl);
 
     if (ps->provDeleteCrl)
-        ret = ps->provDeleteCrl(ps->hStoreProv, crl, 0);
+        ret = ps->provDeleteCrl(ps->hStoreProv, context_ptr(crl), 0);
     if (ret)
-        ret = ps->memStore->crls.deleteContext(ps->memStore, crl);
+        ret = ps->memStore->vtbl->crls.delete(ps->memStore, crl);
     return ret;
 }
 
-static BOOL CRYPT_ProvAddCTL(PWINECRYPT_CERTSTORE store, void *ctl,
void *toReplace, const void **ppStoreContext)
+static BOOL ProvStore_addCTL(WINECRYPT_CERTSTORE *store, context_t *ctl,
context_t *toReplace, context_t **ppStoreContext, BOOL use_link)
 {
-    PWINE_PROVIDERSTORE ps = (PWINE_PROVIDERSTORE)store;
+    WINE_PROVIDERSTORE *ps = (WINE_PROVIDERSTORE*)store;
     BOOL ret;
 
     TRACE("(%p, %p, %p, %p)\n", store, ctl, toReplace, ppStoreContext);
 
     if (toReplace)
-        ret = ps->memStore->ctls.addContext(ps->memStore, ctl, toReplace,
-         ppStoreContext);
+        ret = ps->memStore->vtbl->ctls.addContext(ps->memStore, ctl, toReplace,
+         ppStoreContext, TRUE);
     else
     {
         if (ps->hdr.dwOpenFlags & CERT_STORE_READONLY_FLAG)
@@ -197,58 +218,57 @@ static BOOL CRYPT_ProvAddCTL(PWINECRYPT_CERTSTORE store, void *ctl,
         {
             ret = TRUE;
             if (ps->provWriteCtl)
-                ret = ps->provWriteCtl(ps->hStoreProv, ctl,
+                ret = ps->provWriteCtl(ps->hStoreProv, context_ptr(ctl),
                  CERT_STORE_PROV_WRITE_ADD_FLAG);
             if (ret)
-                ret = ps->memStore->ctls.addContext(ps->memStore, ctl, NULL,
-                 ppStoreContext);
+                ret = ps->memStore->vtbl->ctls.addContext(ps->memStore, ctl, NULL,
+                 ppStoreContext, TRUE);
         }
     }
     /* dirty trick: replace the returned context's hCertStore with
      * store.
      */
     if (ret && ppStoreContext)
-        (*(PCTL_CONTEXT *)ppStoreContext)->hCertStore = store;
+        (*(ctl_t**)ppStoreContext)->ctx.hCertStore = store;
     return ret;
 }
 
-static void *CRYPT_ProvEnumCTL(PWINECRYPT_CERTSTORE store, void *pPrev)
+static context_t *ProvStore_enumCTL(WINECRYPT_CERTSTORE *store, context_t *prev)
 {
-    PWINE_PROVIDERSTORE ps = (PWINE_PROVIDERSTORE)store;
-    void *ret;
+    WINE_PROVIDERSTORE *ps = (WINE_PROVIDERSTORE*)store;
+    ctl_t *ret;
 
-    ret = ps->memStore->ctls.enumContext(ps->memStore, pPrev);
-    if (ret)
-    {
-        /* same dirty trick: replace the returned context's hCertStore with
-         * store.
-         */
-        ((PCTL_CONTEXT)ret)->hCertStore = store;
-    }
-    return ret;
+    ret = (ctl_t*)ps->memStore->vtbl->ctls.enumContext(ps->memStore, prev);
+    if (!ret)
+        return NULL;
+
+    /* same dirty trick: replace the returned context's hCertStore with
+     * store.
+     */
+    ret->ctx.hCertStore = store;
+    return &ret->base;
 }
 
-static BOOL CRYPT_ProvDeleteCTL(PWINECRYPT_CERTSTORE store, void *ctl)
+static BOOL ProvStore_deleteCTL(WINECRYPT_CERTSTORE *store, context_t *ctl)
 {
-    PWINE_PROVIDERSTORE ps = (PWINE_PROVIDERSTORE)store;
+    WINE_PROVIDERSTORE *ps = (WINE_PROVIDERSTORE*)store;
     BOOL ret = TRUE;
 
     TRACE("(%p, %p)\n", store, ctl);
 
     if (ps->provDeleteCtl)
-        ret = ps->provDeleteCtl(ps->hStoreProv, ctl, 0);
+        ret = ps->provDeleteCtl(ps->hStoreProv, context_ptr(ctl), 0);
     if (ret)
-        ret = ps->memStore->ctls.deleteContext(ps->memStore, ctl);
+        ret = ps->memStore->vtbl->ctls.delete(ps->memStore, ctl);
     return ret;
 }
 
-static BOOL WINAPI CRYPT_ProvControl(HCERTSTORE hCertStore, DWORD dwFlags,
- DWORD dwCtrlType, void const *pvCtrlPara)
+static BOOL ProvStore_control(WINECRYPT_CERTSTORE *cert_store, DWORD dwFlags, DWORD dwCtrlType, void const *pvCtrlPara)
 {
-    PWINE_PROVIDERSTORE store = hCertStore;
+    WINE_PROVIDERSTORE *store = (WINE_PROVIDERSTORE*)cert_store;
     BOOL ret = TRUE;
 
-    TRACE("(%p, %08x, %d, %p)\n", hCertStore, dwFlags, dwCtrlType,
+    TRACE("(%p, %08x, %d, %p)\n", store, dwFlags, dwCtrlType,
      pvCtrlPara);
 
     if (store->provControl)
@@ -257,14 +277,34 @@ static BOOL WINAPI CRYPT_ProvControl(HCERTSTORE hCertStore, DWORD dwFlags,
     return ret;
 }
 
-PWINECRYPT_CERTSTORE CRYPT_ProvCreateStore(DWORD dwFlags,
- PWINECRYPT_CERTSTORE memStore, const CERT_STORE_PROV_INFO *pProvInfo)
+static const store_vtbl_t ProvStoreVtbl = {
+    ProvStore_addref,
+    ProvStore_release,
+    ProvStore_releaseContext,
+    ProvStore_control,
+    {
+        ProvStore_addCert,
+        ProvStore_enumCert,
+        ProvStore_deleteCert
+    }, {
+        ProvStore_addCRL,
+        ProvStore_enumCRL,
+        ProvStore_deleteCRL
+    }, {
+        ProvStore_addCTL,
+        ProvStore_enumCTL,
+        ProvStore_deleteCTL
+    }
+};
+
+WINECRYPT_CERTSTORE *CRYPT_ProvCreateStore(DWORD dwFlags,
+ WINECRYPT_CERTSTORE *memStore, const CERT_STORE_PROV_INFO *pProvInfo)
 {
-    PWINE_PROVIDERSTORE ret = CryptMemAlloc(sizeof(WINE_PROVIDERSTORE));
+    WINE_PROVIDERSTORE *ret = CryptMemAlloc(sizeof(WINE_PROVIDERSTORE));
 
     if (ret)
     {
-        CRYPT_InitStore(&ret->hdr, dwFlags, StoreTypeProvider);
+        CRYPT_InitStore(&ret->hdr, dwFlags, StoreTypeProvider, &ProvStoreVtbl);
         ret->dwStoreProvFlags = pProvInfo->dwStoreProvFlags;
         if (ret->dwStoreProvFlags & CERT_STORE_PROV_EXTERNAL_FLAG)
         {
@@ -274,17 +314,6 @@ PWINECRYPT_CERTSTORE CRYPT_ProvCreateStore(DWORD dwFlags,
         else
             ret->memStore = memStore;
         ret->hStoreProv = pProvInfo->hStoreProv;
-        ret->hdr.closeStore = CRYPT_ProvCloseStore;
-        ret->hdr.certs.addContext = CRYPT_ProvAddCert;
-        ret->hdr.certs.enumContext = CRYPT_ProvEnumCert;
-        ret->hdr.certs.deleteContext = CRYPT_ProvDeleteCert;
-        ret->hdr.crls.addContext = CRYPT_ProvAddCRL;
-        ret->hdr.crls.enumContext = CRYPT_ProvEnumCRL;
-        ret->hdr.crls.deleteContext = CRYPT_ProvDeleteCRL;
-        ret->hdr.ctls.addContext = CRYPT_ProvAddCTL;
-        ret->hdr.ctls.enumContext = CRYPT_ProvEnumCTL;
-        ret->hdr.ctls.deleteContext = CRYPT_ProvDeleteCTL;
-        ret->hdr.control = CRYPT_ProvControl;
         if (pProvInfo->cStoreProvFunc > CERT_STORE_PROV_CLOSE_FUNC)
             ret->provCloseStore =
              pProvInfo->rgpvStoreProvFunc[CERT_STORE_PROV_CLOSE_FUNC];
@@ -333,16 +362,16 @@ PWINECRYPT_CERTSTORE CRYPT_ProvCreateStore(DWORD dwFlags,
         else
             ret->provControl = NULL;
     }
-    return (PWINECRYPT_CERTSTORE)ret;
+    return (WINECRYPT_CERTSTORE*)ret;
 }
 
-PWINECRYPT_CERTSTORE CRYPT_ProvOpenStore(LPCSTR lpszStoreProvider,
+WINECRYPT_CERTSTORE *CRYPT_ProvOpenStore(LPCSTR lpszStoreProvider,
  DWORD dwEncodingType, HCRYPTPROV hCryptProv, DWORD dwFlags, const void *pvPara)
 {
     static HCRYPTOIDFUNCSET set = NULL;
     PFN_CERT_DLL_OPEN_STORE_PROV_FUNC provOpenFunc;
     HCRYPTOIDFUNCADDR hFunc;
-    PWINECRYPT_CERTSTORE ret = NULL;
+    WINECRYPT_CERTSTORE *ret = NULL;
 
     if (!set)
         set = CryptInitOIDFunctionSet(CRYPT_OID_OPEN_STORE_PROV_FUNC, 0);
index e5d352e..f90103d 100644 (file)
@@ -24,7 +24,7 @@ typedef struct _WINE_HASH_TO_DELETE
 {
     BYTE        hash[20];
     struct list entry;
-} WINE_HASH_TO_DELETE, *PWINE_HASH_TO_DELETE;
+} WINE_HASH_TO_DELETE;
 
 typedef struct _WINE_REGSTOREINFO
 {
@@ -36,7 +36,7 @@ typedef struct _WINE_REGSTOREINFO
     struct list      certsToDelete;
     struct list      crlsToDelete;
     struct list      ctlsToDelete;
-} WINE_REGSTOREINFO, *PWINE_REGSTOREINFO;
+} WINE_REGSTOREINFO;
 
 static void CRYPT_HashToStr(const BYTE *hash, LPWSTR asciiHash)
 {
@@ -135,7 +135,7 @@ static void CRYPT_RegReadSerializedFromReg(HKEY key, DWORD contextType,
                                     else
                                         TRACE("hash doesn't match, ignoring\n");
                                 }
-                                contextInterface->free(context);
+                                Context_Release(context_from_ptr(context));
                             }
                         }
                     }
@@ -234,11 +234,11 @@ static BOOL CRYPT_SerializeContextsToReg(HKEY key,
             ret = TRUE;
     } while (ret && context != NULL);
     if (context)
-        contextInterface->free(context);
+        Context_Release(context_from_ptr(context));
     return ret;
 }
 
-static BOOL CRYPT_RegWriteToReg(PWINE_REGSTOREINFO store)
+static BOOL CRYPT_RegWriteToReg(WINE_REGSTOREINFO *store)
 {
     static const WCHAR * const subKeys[] = { CertsW, CRLsW, CTLsW };
     const WINE_CONTEXT_INTERFACE * const interfaces[] = { pCertInterface,
@@ -258,7 +258,7 @@ static BOOL CRYPT_RegWriteToReg(PWINE_REGSTOREINFO store)
         {
             if (listToDelete[i])
             {
-                PWINE_HASH_TO_DELETE toDelete, next;
+                WINE_HASH_TO_DELETE *toDelete, *next;
                 WCHAR asciiHash[20 * 2 + 1];
 
                 EnterCriticalSection(&store->cs);
@@ -296,7 +296,7 @@ static BOOL CRYPT_RegWriteToReg(PWINE_REGSTOREINFO store)
 /* If force is true or the registry store is dirty, writes the contents of the
  * store to the registry.
  */
-static BOOL CRYPT_RegFlushStore(PWINE_REGSTOREINFO store, BOOL force)
+static BOOL CRYPT_RegFlushStore(WINE_REGSTOREINFO *store, BOOL force)
 {
     BOOL ret;
 
@@ -311,7 +311,7 @@ static BOOL CRYPT_RegFlushStore(PWINE_REGSTOREINFO store, BOOL force)
 
 static void WINAPI CRYPT_RegCloseStore(HCERTSTORE hCertStore, DWORD dwFlags)
 {
-    PWINE_REGSTOREINFO store = hCertStore;
+    WINE_REGSTOREINFO *store = hCertStore;
 
     TRACE("(%p, %08x)\n", store, dwFlags);
     if (dwFlags)
@@ -324,7 +324,7 @@ static void WINAPI CRYPT_RegCloseStore(HCERTSTORE hCertStore, DWORD dwFlags)
     CryptMemFree(store);
 }
 
-static BOOL CRYPT_RegWriteContext(PWINE_REGSTOREINFO store,
+static BOOL CRYPT_RegWriteContext(WINE_REGSTOREINFO *store,
  const void *context, DWORD dwFlags)
 {
     BOOL ret;
@@ -339,9 +339,9 @@ static BOOL CRYPT_RegWriteContext(PWINE_REGSTOREINFO store,
     return ret;
 }
 
-static BOOL CRYPT_RegDeleteContext(PWINE_REGSTOREINFO store,
+static BOOL CRYPT_RegDeleteContext(WINE_REGSTOREINFO *store,
  struct list *deleteList, const void *context,
PCWINE_CONTEXT_INTERFACE contextInterface)
const WINE_CONTEXT_INTERFACE *contextInterface)
 {
     BOOL ret;
 
@@ -352,8 +352,7 @@ static BOOL CRYPT_RegDeleteContext(PWINE_REGSTOREINFO store,
     }
     else
     {
-        PWINE_HASH_TO_DELETE toDelete =
-         CryptMemAlloc(sizeof(WINE_HASH_TO_DELETE));
+        WINE_HASH_TO_DELETE *toDelete = CryptMemAlloc(sizeof(WINE_HASH_TO_DELETE));
 
         if (toDelete)
         {
@@ -384,7 +383,7 @@ static BOOL CRYPT_RegDeleteContext(PWINE_REGSTOREINFO store,
 static BOOL WINAPI CRYPT_RegWriteCert(HCERTSTORE hCertStore,
  PCCERT_CONTEXT cert, DWORD dwFlags)
 {
-    PWINE_REGSTOREINFO store = hCertStore;
+    WINE_REGSTOREINFO *store = hCertStore;
 
     TRACE("(%p, %p, %d)\n", hCertStore, cert, dwFlags);
 
@@ -394,7 +393,7 @@ static BOOL WINAPI CRYPT_RegWriteCert(HCERTSTORE hCertStore,
 static BOOL WINAPI CRYPT_RegDeleteCert(HCERTSTORE hCertStore,
  PCCERT_CONTEXT pCertContext, DWORD dwFlags)
 {
-    PWINE_REGSTOREINFO store = hCertStore;
+    WINE_REGSTOREINFO *store = hCertStore;
 
     TRACE("(%p, %p, %08x)\n", store, pCertContext, dwFlags);
 
@@ -405,7 +404,7 @@ static BOOL WINAPI CRYPT_RegDeleteCert(HCERTSTORE hCertStore,
 static BOOL WINAPI CRYPT_RegWriteCRL(HCERTSTORE hCertStore,
  PCCRL_CONTEXT crl, DWORD dwFlags)
 {
-    PWINE_REGSTOREINFO store = hCertStore;
+    WINE_REGSTOREINFO *store = hCertStore;
 
     TRACE("(%p, %p, %d)\n", hCertStore, crl, dwFlags);
 
@@ -415,7 +414,7 @@ static BOOL WINAPI CRYPT_RegWriteCRL(HCERTSTORE hCertStore,
 static BOOL WINAPI CRYPT_RegDeleteCRL(HCERTSTORE hCertStore,
  PCCRL_CONTEXT pCrlContext, DWORD dwFlags)
 {
-    PWINE_REGSTOREINFO store = hCertStore;
+    WINE_REGSTOREINFO *store = hCertStore;
 
     TRACE("(%p, %p, %08x)\n", store, pCrlContext, dwFlags);
 
@@ -426,7 +425,7 @@ static BOOL WINAPI CRYPT_RegDeleteCRL(HCERTSTORE hCertStore,
 static BOOL WINAPI CRYPT_RegWriteCTL(HCERTSTORE hCertStore,
  PCCTL_CONTEXT ctl, DWORD dwFlags)
 {
-    PWINE_REGSTOREINFO store = hCertStore;
+    WINE_REGSTOREINFO *store = hCertStore;
 
     TRACE("(%p, %p, %d)\n", hCertStore, ctl, dwFlags);
 
@@ -436,7 +435,7 @@ static BOOL WINAPI CRYPT_RegWriteCTL(HCERTSTORE hCertStore,
 static BOOL WINAPI CRYPT_RegDeleteCTL(HCERTSTORE hCertStore,
  PCCTL_CONTEXT pCtlContext, DWORD dwFlags)
 {
-    PWINE_REGSTOREINFO store = hCertStore;
+    WINE_REGSTOREINFO *store = hCertStore;
 
     TRACE("(%p, %p, %08x)\n", store, pCtlContext, dwFlags);
 
@@ -447,7 +446,7 @@ static BOOL WINAPI CRYPT_RegDeleteCTL(HCERTSTORE hCertStore,
 static BOOL WINAPI CRYPT_RegControl(HCERTSTORE hCertStore, DWORD dwFlags,
  DWORD dwCtrlType, void const *pvCtrlPara)
 {
-    PWINE_REGSTOREINFO store = hCertStore;
+    WINE_REGSTOREINFO *store = hCertStore;
     BOOL ret;
 
     TRACE("(%p, %08x, %d, %p)\n", hCertStore, dwFlags, dwCtrlType,
@@ -499,10 +498,10 @@ static void *regProvFuncs[] = {
     CRYPT_RegControl,
 };
 
-PWINECRYPT_CERTSTORE CRYPT_RegOpenStore(HCRYPTPROV hCryptProv, DWORD dwFlags,
+WINECRYPT_CERTSTORE *CRYPT_RegOpenStore(HCRYPTPROV hCryptProv, DWORD dwFlags,
  const void *pvPara)
 {
-    PWINECRYPT_CERTSTORE store = NULL;
+    WINECRYPT_CERTSTORE *store = NULL;
 
     TRACE("(%ld, %08x, %p)\n", hCryptProv, dwFlags, pvPara);
 
@@ -527,13 +526,13 @@ PWINECRYPT_CERTSTORE CRYPT_RegOpenStore(HCRYPTPROV hCryptProv, DWORD dwFlags,
          dwFlags & CERT_STORE_READONLY_FLAG ? KEY_READ : KEY_ALL_ACCESS,
          TRUE, 0))
         {
-            PWINECRYPT_CERTSTORE memStore;
+            WINECRYPT_CERTSTORE *memStore;
 
             memStore = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, hCryptProv,
              CERT_STORE_CREATE_NEW_FLAG, NULL);
             if (memStore)
             {
-                PWINE_REGSTOREINFO regInfo = CryptMemAlloc(
+                WINE_REGSTOREINFO *regInfo = CryptMemAlloc(
                  sizeof(WINE_REGSTOREINFO));
 
                 if (regInfo)
index 6f82832..414b0d8 100644 (file)
@@ -236,7 +236,7 @@ static void check_and_store_certs(HCERTSTORE from, HCERTSTORE to)
     TRACE("\n");
 
     CertDuplicateStore(to);
-    engine = CRYPT_CreateChainEngine(to, &chainEngineConfig);
+    engine = CRYPT_CreateChainEngine(to, CERT_SYSTEM_STORE_CURRENT_USER, &chainEngineConfig);
     if (engine)
     {
         PCCERT_CONTEXT cert = NULL;
@@ -247,9 +247,10 @@ static void check_and_store_certs(HCERTSTORE from, HCERTSTORE to)
             {
                 CERT_CHAIN_PARA chainPara = { sizeof(chainPara), { 0 } };
                 PCCERT_CHAIN_CONTEXT chain;
-                BOOL ret = CertGetCertificateChain(engine, cert, NULL, from,
-                 &chainPara, 0, NULL, &chain);
+                BOOL ret;
 
+                ret = CertGetCertificateChain(engine, cert, NULL, from,
+                 &chainPara, CERT_CHAIN_CACHE_ONLY_URL_RETRIEVAL, NULL, &chain);
                 if (!ret)
                     TRACE("rejecting %s: %s\n", get_cert_common_name(cert),
                      "chain creation failed");
@@ -478,6 +479,7 @@ static const char * const CRYPT_knownLocations[] = {
  "/etc/ssl/certs/ca-certificates.crt",
  "/etc/ssl/certs",
  "/etc/pki/tls/certs/ca-bundle.crt",
+ "/usr/share/ca-certificates/ca-bundle.crt",
  "/usr/local/share/certs/",
  "/etc/sfw/openssl/certs",
 };
@@ -803,9 +805,9 @@ static HCERTSTORE create_root_store(void)
     return root;
 }
 
-static PWINECRYPT_CERTSTORE CRYPT_rootStore;
+static WINECRYPT_CERTSTORE *CRYPT_rootStore;
 
-PWINECRYPT_CERTSTORE CRYPT_RootOpenStore(HCRYPTPROV hCryptProv, DWORD dwFlags)
+WINECRYPT_CERTSTORE *CRYPT_RootOpenStore(HCRYPTPROV hCryptProv, DWORD dwFlags)
 {
     TRACE("(%ld, %08x)\n", hCryptProv, dwFlags);
 
@@ -824,7 +826,7 @@ PWINECRYPT_CERTSTORE CRYPT_RootOpenStore(HCRYPTPROV hCryptProv, DWORD dwFlags)
         if (CRYPT_rootStore != root)
             CertCloseStore(root, 0);
     }
-    CertDuplicateStore(CRYPT_rootStore);
+    CRYPT_rootStore->vtbl->addref(CRYPT_rootStore);
     return CRYPT_rootStore;
 }
 
index 23b0172..b722d21 100644 (file)
@@ -28,11 +28,11 @@ typedef struct _WINE_CERT_PROP_HEADER
     DWORD propID;
     DWORD unknown; /* always 1 */
     DWORD cb;
-} WINE_CERT_PROP_HEADER, *PWINE_CERT_PROP_HEADER;
+} WINE_CERT_PROP_HEADER;
 
 static BOOL CRYPT_SerializeStoreElement(const void *context,
  const BYTE *encodedContext, DWORD cbEncodedContext, DWORD contextPropID,
PCWINE_CONTEXT_INTERFACE contextInterface, DWORD dwFlags, BOOL omitHashes,
const WINE_CONTEXT_INTERFACE *contextInterface, DWORD dwFlags, BOOL omitHashes,
  BYTE *pbElement, DWORD *pcbElement)
 {
     BOOL ret;
@@ -71,7 +71,7 @@ static BOOL CRYPT_SerializeStoreElement(const void *context,
         }
         else
         {
-            PWINE_CERT_PROP_HEADER hdr;
+            WINE_CERT_PROP_HEADER *hdr;
             DWORD bufSize = 0;
             LPBYTE buf = NULL;
 
@@ -100,7 +100,7 @@ static BOOL CRYPT_SerializeStoreElement(const void *context,
                              &propSize);
                             if (ret)
                             {
-                                hdr = (PWINE_CERT_PROP_HEADER)pbElement;
+                                hdr = (WINE_CERT_PROP_HEADER*)pbElement;
                                 hdr->propID = prop;
                                 hdr->unknown = 1;
                                 hdr->cb = propSize;
@@ -119,7 +119,7 @@ static BOOL CRYPT_SerializeStoreElement(const void *context,
             } while (ret && prop != 0);
             CryptMemFree(buf);
 
-            hdr = (PWINE_CERT_PROP_HEADER)pbElement;
+            hdr = (WINE_CERT_PROP_HEADER*)pbElement;
             hdr->propID = contextPropID;
             hdr->unknown = 1;
             hdr->cb = cbEncodedContext;
@@ -400,7 +400,7 @@ const void *CRYPT_ReadSerializedElement(const BYTE *pbElement, DWORD cbElement,
             }
             else
             {
-                contextInterface->free(context);
+                Context_Release(context_from_ptr(context));
                 context = NULL;
             }
         }
@@ -452,7 +452,7 @@ static BOOL CRYPT_ReadSerializedStore(void *handle,
                      propHdr.propID == CERT_CTL_PROP_ID))
                     {
                         /* We have a new context, so free the existing one */
-                        contextInterface->free(context);
+                        Context_Release(context_from_ptr(context));
                     }
                     if (propHdr.cb > bufSize)
                     {
@@ -513,7 +513,7 @@ static BOOL CRYPT_ReadSerializedStore(void *handle,
             if (contextInterface && context)
             {
                 /* Free the last context added */
-                contextInterface->free(context);
+                Context_Release(context_from_ptr(context));
             }
             CryptMemFree(buf);
             ret = TRUE;
@@ -629,7 +629,7 @@ static BOOL CRYPT_SerializeContextsToStream(SerializedOutputFunc output,
             ret = TRUE;
     } while (ret && context != NULL);
     if (context)
-        contextInterface->free(context);
+        Context_Release(context_from_ptr(context));
     return ret;
 }
 
@@ -987,7 +987,7 @@ BOOL WINAPI CertAddSerializedElementToStore(HCERTSTORE hCertStore,
                 *pdwContentType = type;
             ret = contextInterface->addContextToStore(hCertStore, context,
              dwAddDisposition, ppvContext);
-            contextInterface->free(context);
+            Context_Release(context_from_ptr(context));
         }
         else
             ret = FALSE;
index 1d6ccb8..b0a77f6 100644 (file)
@@ -31,69 +31,65 @@ static const WINE_CONTEXT_INTERFACE gCertInterface = {
     (CreateContextFunc)CertCreateCertificateContext,
     (AddContextToStoreFunc)CertAddCertificateContextToStore,
     (AddEncodedContextToStoreFunc)CertAddEncodedCertificateToStore,
-    (DuplicateContextFunc)CertDuplicateCertificateContext,
     (EnumContextsInStoreFunc)CertEnumCertificatesInStore,
     (EnumPropertiesFunc)CertEnumCertificateContextProperties,
     (GetContextPropertyFunc)CertGetCertificateContextProperty,
     (SetContextPropertyFunc)CertSetCertificateContextProperty,
     (SerializeElementFunc)CertSerializeCertificateStoreElement,
-    (FreeContextFunc)CertFreeCertificateContext,
     (DeleteContextFunc)CertDeleteCertificateFromStore,
 };
-PCWINE_CONTEXT_INTERFACE pCertInterface = &gCertInterface;
+const WINE_CONTEXT_INTERFACE *pCertInterface = &gCertInterface;
 
 static const WINE_CONTEXT_INTERFACE gCRLInterface = {
     (CreateContextFunc)CertCreateCRLContext,
     (AddContextToStoreFunc)CertAddCRLContextToStore,
     (AddEncodedContextToStoreFunc)CertAddEncodedCRLToStore,
-    (DuplicateContextFunc)CertDuplicateCRLContext,
     (EnumContextsInStoreFunc)CertEnumCRLsInStore,
     (EnumPropertiesFunc)CertEnumCRLContextProperties,
     (GetContextPropertyFunc)CertGetCRLContextProperty,
     (SetContextPropertyFunc)CertSetCRLContextProperty,
     (SerializeElementFunc)CertSerializeCRLStoreElement,
-    (FreeContextFunc)CertFreeCRLContext,
     (DeleteContextFunc)CertDeleteCRLFromStore,
 };
-PCWINE_CONTEXT_INTERFACE pCRLInterface = &gCRLInterface;
+const WINE_CONTEXT_INTERFACE *pCRLInterface = &gCRLInterface;
 
 static const WINE_CONTEXT_INTERFACE gCTLInterface = {
     (CreateContextFunc)CertCreateCTLContext,
     (AddContextToStoreFunc)CertAddCTLContextToStore,
     (AddEncodedContextToStoreFunc)CertAddEncodedCTLToStore,
-    (DuplicateContextFunc)CertDuplicateCTLContext,
     (EnumContextsInStoreFunc)CertEnumCTLsInStore,
     (EnumPropertiesFunc)CertEnumCTLContextProperties,
     (GetContextPropertyFunc)CertGetCTLContextProperty,
     (SetContextPropertyFunc)CertSetCTLContextProperty,
     (SerializeElementFunc)CertSerializeCTLStoreElement,
-    (FreeContextFunc)CertFreeCTLContext,
     (DeleteContextFunc)CertDeleteCTLFromStore,
 };
-PCWINE_CONTEXT_INTERFACE pCTLInterface = &gCTLInterface;
+const WINE_CONTEXT_INTERFACE *pCTLInterface = &gCTLInterface;
 
 typedef struct _WINE_MEMSTORE
 {
     WINECRYPT_CERTSTORE hdr;
-    struct ContextList *certs;
-    struct ContextList *crls;
-    struct ContextList *ctls;
-} WINE_MEMSTORE, *PWINE_MEMSTORE;
+    CRITICAL_SECTION cs;
+    struct list certs;
+    struct list crls;
+    struct list ctls;
+} WINE_MEMSTORE;
 
-void CRYPT_InitStore(WINECRYPT_CERTSTORE *store, DWORD dwFlags,
- CertStoreType type)
+void CRYPT_InitStore(WINECRYPT_CERTSTORE *store, DWORD dwFlags, CertStoreType type, const store_vtbl_t *vtbl)
 {
     store->ref = 1;
     store->dwMagic = WINE_CRYPTCERTSTORE_MAGIC;
     store->type = type;
     store->dwOpenFlags = dwFlags;
+    store->vtbl = vtbl;
     store->properties = NULL;
 }
 
-void CRYPT_FreeStore(PWINECRYPT_CERTSTORE store)
+void CRYPT_FreeStore(WINECRYPT_CERTSTORE *store)
 {
     if (store->properties)
         ContextPropertyList_Free(store->properties);
+    store->dwMagic = 0;
     CryptMemFree(store);
 }
 
@@ -134,166 +130,239 @@ BOOL WINAPI I_CertUpdateStore(HCERTSTORE store1, HCERTSTORE store2, DWORD unk0,
     return TRUE;
 }
 
-static BOOL CRYPT_MemAddCert(PWINECRYPT_CERTSTORE store, void *cert,
void *toReplace, const void **ppStoreContext)
+static BOOL MemStore_addContext(WINE_MEMSTORE *store, struct list *list, context_t *orig_context,
context_t *existing, context_t **ret_context, BOOL use_link)
 {
-    WINE_MEMSTORE *ms = (WINE_MEMSTORE *)store;
-    PCERT_CONTEXT context;
+    context_t *context;
 
-    TRACE("(%p, %p, %p, %p)\n", store, cert, toReplace, ppStoreContext);
+    context = orig_context->vtbl->clone(orig_context, &store->hdr, use_link);
+    if (!context)
+        return FALSE;
+
+    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);
+        if(!existing->ref)
+            Context_Release(existing);
+    }else {
+        list_add_head(list, &context->u.entry);
+    }
+    LeaveCriticalSection(&store->cs);
+
+    if(ret_context)
+        *ret_context = context;
+    else
+        Context_Release(context);
+    return TRUE;
+}
+
+static context_t *MemStore_enumContext(WINE_MEMSTORE *store, struct list *list, context_t *prev)
+{
+    struct list *next;
+    context_t *ret;
+
+    EnterCriticalSection(&store->cs);
+    if (prev) {
+        next = list_next(list, &prev->u.entry);
+        Context_Release(prev);
+    }else {
+        next = list_next(list, list);
+    }
+    LeaveCriticalSection(&store->cs);
+
+    if (!next) {
+        SetLastError(CRYPT_E_NOT_FOUND);
+        return NULL;
+    }
 
-    context = ContextList_Add(ms->certs, cert, toReplace);
-    if (context)
+    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;
+    }
+    LeaveCriticalSection(&store->cs);
+
+    if(in_list && !context->ref)
+        Context_Free(context);
+    return TRUE;
+}
+
+static void free_contexts(struct list *list)
+{
+    context_t *context, *next;
+
+    LIST_FOR_EACH_ENTRY_SAFE(context, next, list, context_t, u.entry)
     {
-        context->hCertStore = store;
-        if (ppStoreContext)
-            *ppStoreContext = CertDuplicateCertificateContext(context);
+        TRACE("freeing %p\n", context);
+        list_remove(&context->u.entry);
+        Context_Free(context);
     }
-    return context != 0;
 }
 
-static void *CRYPT_MemEnumCert(PWINECRYPT_CERTSTORE store, void *pPrev)
+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))
+        Context_Free(context);
+}
+
+static BOOL MemStore_addCert(WINECRYPT_CERTSTORE *store, context_t *cert,
+ context_t *toReplace, context_t **ppStoreContext, BOOL use_link)
 {
     WINE_MEMSTORE *ms = (WINE_MEMSTORE *)store;
-    void *ret;
 
-    TRACE("(%p, %p)\n", store, pPrev);
+    TRACE("(%p, %p, %p, %p)\n", store, cert, toReplace, ppStoreContext);
+    return MemStore_addContext(ms, &ms->certs, cert, toReplace, ppStoreContext, use_link);
+}
 
-    ret = ContextList_Enum(ms->certs, pPrev);
-    if (!ret)
-        SetLastError(CRYPT_E_NOT_FOUND);
+static context_t *MemStore_enumCert(WINECRYPT_CERTSTORE *store, context_t *prev)
+{
+    WINE_MEMSTORE *ms = (WINE_MEMSTORE *)store;
 
-    TRACE("returning %p\n", ret);
-    return ret;
+    TRACE("(%p, %p)\n", store, prev);
+
+    return MemStore_enumContext(ms, &ms->certs, prev);
 }
 
-static BOOL CRYPT_MemDeleteCert(PWINECRYPT_CERTSTORE store, void *pCertContext)
+static BOOL MemStore_deleteCert(WINECRYPT_CERTSTORE *store, context_t *context)
 {
     WINE_MEMSTORE *ms = (WINE_MEMSTORE *)store;
-    BOOL ret;
 
-    if (ContextList_Remove(ms->certs, pCertContext))
-        ret = CertFreeCertificateContext(pCertContext);
-    else
-        ret = TRUE;
-    return ret;
+    TRACE("(%p, %p)\n", store, context);
+
+    return MemStore_deleteContext(ms, context);
 }
 
-static BOOL CRYPT_MemAddCrl(PWINECRYPT_CERTSTORE store, void *crl,
void *toReplace, const void **ppStoreContext)
+static BOOL MemStore_addCRL(WINECRYPT_CERTSTORE *store, context_t *crl,
context_t *toReplace, context_t **ppStoreContext, BOOL use_link)
 {
     WINE_MEMSTORE *ms = (WINE_MEMSTORE *)store;
-    PCRL_CONTEXT context;
 
     TRACE("(%p, %p, %p, %p)\n", store, crl, toReplace, ppStoreContext);
 
-    context = ContextList_Add(ms->crls, crl, toReplace);
-    if (context)
-    {
-        context->hCertStore = store;
-        if (ppStoreContext)
-            *ppStoreContext = CertDuplicateCRLContext(context);
-    }
-    return context != 0;
+    return MemStore_addContext(ms, &ms->crls, crl, toReplace, ppStoreContext, use_link);
 }
 
-static void *CRYPT_MemEnumCrl(PWINECRYPT_CERTSTORE store, void *pPrev)
+static context_t *MemStore_enumCRL(WINECRYPT_CERTSTORE *store, context_t *prev)
 {
     WINE_MEMSTORE *ms = (WINE_MEMSTORE *)store;
-    void *ret;
 
-    TRACE("(%p, %p)\n", store, pPrev);
+    TRACE("(%p, %p)\n", store, prev);
 
-    ret = ContextList_Enum(ms->crls, pPrev);
-    if (!ret)
-        SetLastError(CRYPT_E_NOT_FOUND);
-
-    TRACE("returning %p\n", ret);
-    return ret;
+    return MemStore_enumContext(ms, &ms->crls, prev);
 }
 
-static BOOL CRYPT_MemDeleteCrl(PWINECRYPT_CERTSTORE store, void *pCrlContext)
+static BOOL MemStore_deleteCRL(WINECRYPT_CERTSTORE *store, context_t *context)
 {
     WINE_MEMSTORE *ms = (WINE_MEMSTORE *)store;
-    BOOL ret;
 
-    if (ContextList_Remove(ms->crls, pCrlContext))
-        ret = CertFreeCRLContext(pCrlContext);
-    else
-        ret = TRUE;
-    return ret;
+    TRACE("(%p, %p)\n", store, context);
+
+    return MemStore_deleteContext(ms, context);
 }
 
-static BOOL CRYPT_MemAddCtl(PWINECRYPT_CERTSTORE store, void *ctl,
void *toReplace, const void **ppStoreContext)
+static BOOL MemStore_addCTL(WINECRYPT_CERTSTORE *store, context_t *ctl,
context_t *toReplace, context_t **ppStoreContext, BOOL use_link)
 {
     WINE_MEMSTORE *ms = (WINE_MEMSTORE *)store;
-    PCTL_CONTEXT context;
 
     TRACE("(%p, %p, %p, %p)\n", store, ctl, toReplace, ppStoreContext);
 
-    context = ContextList_Add(ms->ctls, ctl, toReplace);
-    if (context)
-    {
-        context->hCertStore = store;
-        if (ppStoreContext)
-            *ppStoreContext = CertDuplicateCTLContext(context);
-    }
-    return context != 0;
+    return MemStore_addContext(ms, &ms->ctls, ctl, toReplace, ppStoreContext, use_link);
 }
 
-static void *CRYPT_MemEnumCtl(PWINECRYPT_CERTSTORE store, void *pPrev)
+static context_t *MemStore_enumCTL(WINECRYPT_CERTSTORE *store, context_t *prev)
 {
     WINE_MEMSTORE *ms = (WINE_MEMSTORE *)store;
-    void *ret;
 
-    TRACE("(%p, %p)\n", store, pPrev);
+    TRACE("(%p, %p)\n", store, prev);
 
-    ret = ContextList_Enum(ms->ctls, pPrev);
-    if (!ret)
-        SetLastError(CRYPT_E_NOT_FOUND);
-
-    TRACE("returning %p\n", ret);
-    return ret;
+    return MemStore_enumContext(ms, &ms->ctls, prev);
 }
 
-static BOOL CRYPT_MemDeleteCtl(PWINECRYPT_CERTSTORE store, void *pCtlContext)
+static BOOL MemStore_deleteCTL(WINECRYPT_CERTSTORE *store, context_t *context)
 {
     WINE_MEMSTORE *ms = (WINE_MEMSTORE *)store;
-    BOOL ret;
 
-    if (ContextList_Remove(ms->ctls, pCtlContext))
-        ret = CertFreeCTLContext(pCtlContext);
-    else
-        ret = TRUE;
-    return ret;
+    TRACE("(%p, %p)\n", store, context);
+
+    return MemStore_deleteContext(ms, context);
 }
 
-static BOOL WINAPI CRYPT_MemControl(HCERTSTORE hCertStore, DWORD dwFlags,
- DWORD dwCtrlType, void const *pvCtrlPara)
+static void MemStore_addref(WINECRYPT_CERTSTORE *store)
 {
-    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-    return FALSE;
+    LONG ref = InterlockedIncrement(&store->ref);
+    TRACE("ref = %d\n", ref);
 }
 
-static void WINAPI CRYPT_MemCloseStore(HCERTSTORE hCertStore, DWORD dwFlags)
+static DWORD MemStore_release(WINECRYPT_CERTSTORE *cert_store, DWORD flags)
 {
-    WINE_MEMSTORE *store = hCertStore;
-
-    TRACE("(%p, %08x)\n", store, dwFlags);
-    if (dwFlags)
-        FIXME("Unimplemented flags: %08x\n", dwFlags);
+    WINE_MEMSTORE *store = (WINE_MEMSTORE*)cert_store;
+    LONG ref;
+
+    if(flags & ~CERT_CLOSE_STORE_CHECK_FLAG)
+        FIXME("Unimplemented flags %x\n", flags);
+
+    ref = InterlockedDecrement(&store->hdr.ref);
+    TRACE("(%p) ref=%d\n", store, ref);
+    if(ref)
+        return (flags & CERT_CLOSE_STORE_CHECK_FLAG) ? CRYPT_E_PENDING_CLOSE : ERROR_SUCCESS;
+
+    free_contexts(&store->certs);
+    free_contexts(&store->crls);
+    free_contexts(&store->ctls);
+    store->cs.DebugInfo->Spare[0] = 0;
+    DeleteCriticalSection(&store->cs);
+    CRYPT_FreeStore(&store->hdr);
+    return ERROR_SUCCESS;
+}
 
-    ContextList_Free(store->certs);
-    ContextList_Free(store->crls);
-    ContextList_Free(store->ctls);
-    CRYPT_FreeStore((PWINECRYPT_CERTSTORE)store);
+static BOOL MemStore_control(WINECRYPT_CERTSTORE *store, DWORD dwFlags,
+ DWORD dwCtrlType, void const *pvCtrlPara)
+{
+    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+    return FALSE;
 }
 
+static const store_vtbl_t MemStoreVtbl = {
+    MemStore_addref,
+    MemStore_release,
+    MemStore_releaseContext,
+    MemStore_control,
+    {
+        MemStore_addCert,
+        MemStore_enumCert,
+        MemStore_deleteCert
+    }, {
+        MemStore_addCRL,
+        MemStore_enumCRL,
+        MemStore_deleteCRL
+    }, {
+        MemStore_addCTL,
+        MemStore_enumCTL,
+        MemStore_deleteCTL
+    }
+};
+
 static WINECRYPT_CERTSTORE *CRYPT_MemOpenStore(HCRYPTPROV hCryptProv,
  DWORD dwFlags, const void *pvPara)
 {
-    PWINE_MEMSTORE store;
+    WINE_MEMSTORE *store;
 
     TRACE("(%ld, %08x, %p)\n", hCryptProv, dwFlags, pvPara);
 
@@ -308,41 +377,29 @@ static WINECRYPT_CERTSTORE *CRYPT_MemOpenStore(HCRYPTPROV hCryptProv,
         if (store)
         {
             memset(store, 0, sizeof(WINE_MEMSTORE));
-            CRYPT_InitStore(&store->hdr, dwFlags, StoreTypeMem);
-            store->hdr.closeStore          = CRYPT_MemCloseStore;
-            store->hdr.certs.addContext    = CRYPT_MemAddCert;
-            store->hdr.certs.enumContext   = CRYPT_MemEnumCert;
-            store->hdr.certs.deleteContext = CRYPT_MemDeleteCert;
-            store->hdr.crls.addContext     = CRYPT_MemAddCrl;
-            store->hdr.crls.enumContext    = CRYPT_MemEnumCrl;
-            store->hdr.crls.deleteContext  = CRYPT_MemDeleteCrl;
-            store->hdr.ctls.addContext     = CRYPT_MemAddCtl;
-            store->hdr.ctls.enumContext    = CRYPT_MemEnumCtl;
-            store->hdr.ctls.deleteContext  = CRYPT_MemDeleteCtl;
-            store->hdr.control             = CRYPT_MemControl;
-            store->certs = ContextList_Create(pCertInterface,
-             sizeof(CERT_CONTEXT));
-            store->crls = ContextList_Create(pCRLInterface,
-             sizeof(CRL_CONTEXT));
-            store->ctls = ContextList_Create(pCTLInterface,
-             sizeof(CTL_CONTEXT));
+            CRYPT_InitStore(&store->hdr, dwFlags, StoreTypeMem, &MemStoreVtbl);
+            InitializeCriticalSection(&store->cs);
+            store->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": ContextList.cs");
+            list_init(&store->certs);
+            list_init(&store->crls);
+            list_init(&store->ctls);
             /* Mem store doesn't need crypto provider, so close it */
             if (hCryptProv && !(dwFlags & CERT_STORE_NO_CRYPT_RELEASE_FLAG))
                 CryptReleaseContext(hCryptProv, 0);
         }
     }
-    return (PWINECRYPT_CERTSTORE)store;
+    return (WINECRYPT_CERTSTORE*)store;
 }
 
 static const WCHAR rootW[] = { 'R','o','o','t',0 };
 
-static PWINECRYPT_CERTSTORE CRYPT_SysRegOpenStoreW(HCRYPTPROV hCryptProv,
+static WINECRYPT_CERTSTORE *CRYPT_SysRegOpenStoreW(HCRYPTPROV hCryptProv,
  DWORD dwFlags, const void *pvPara)
 {
     static const WCHAR fmt[] = { '%','s','\\','%','s',0 };
     LPCWSTR storeName = pvPara;
     LPWSTR storePath;
-    PWINECRYPT_CERTSTORE store = NULL;
+    WINECRYPT_CERTSTORE *store = NULL;
     HKEY root;
     LPCWSTR base;
 
@@ -448,11 +505,11 @@ static PWINECRYPT_CERTSTORE CRYPT_SysRegOpenStoreW(HCRYPTPROV hCryptProv,
     return store;
 }
 
-static PWINECRYPT_CERTSTORE CRYPT_SysRegOpenStoreA(HCRYPTPROV hCryptProv,
+static WINECRYPT_CERTSTORE *CRYPT_SysRegOpenStoreA(HCRYPTPROV hCryptProv,
  DWORD dwFlags, const void *pvPara)
 {
     int len;
-    PWINECRYPT_CERTSTORE ret = NULL;
+    WINECRYPT_CERTSTORE *ret = NULL;
 
     TRACE("(%ld, %08x, %s)\n", hCryptProv, dwFlags,
      debugstr_a(pvPara));
@@ -477,7 +534,7 @@ static PWINECRYPT_CERTSTORE CRYPT_SysRegOpenStoreA(HCRYPTPROV hCryptProv,
     return ret;
 }
 
-static PWINECRYPT_CERTSTORE CRYPT_SysOpenStoreW(HCRYPTPROV hCryptProv,
+static WINECRYPT_CERTSTORE *CRYPT_SysOpenStoreW(HCRYPTPROV hCryptProv,
  DWORD dwFlags, const void *pvPara)
 {
     HCERTSTORE store = 0;
@@ -549,11 +606,11 @@ static PWINECRYPT_CERTSTORE CRYPT_SysOpenStoreW(HCRYPTPROV hCryptProv,
     return store;
 }
 
-static PWINECRYPT_CERTSTORE CRYPT_SysOpenStoreA(HCRYPTPROV hCryptProv,
+static WINECRYPT_CERTSTORE *CRYPT_SysOpenStoreA(HCRYPTPROV hCryptProv,
  DWORD dwFlags, const void *pvPara)
 {
     int len;
-    PWINECRYPT_CERTSTORE ret = NULL;
+    WINECRYPT_CERTSTORE *ret = NULL;
 
     TRACE("(%ld, %08x, %s)\n", hCryptProv, dwFlags,
      debugstr_a(pvPara));
@@ -590,12 +647,12 @@ static void *msgProvFuncs[] = {
     CRYPT_MsgCloseStore,
 };
 
-static PWINECRYPT_CERTSTORE CRYPT_MsgOpenStore(HCRYPTPROV hCryptProv,
+static WINECRYPT_CERTSTORE *CRYPT_MsgOpenStore(HCRYPTPROV hCryptProv,
  DWORD dwFlags, const void *pvPara)
 {
-    PWINECRYPT_CERTSTORE store = NULL;
+    WINECRYPT_CERTSTORE *store = NULL;
     HCRYPTMSG msg = (HCRYPTMSG)pvPara;
-    PWINECRYPT_CERTSTORE memStore;
+    WINECRYPT_CERTSTORE *memStore;
 
     TRACE("(%ld, %08x, %p)\n", hCryptProv, dwFlags, pvPara);
 
@@ -669,11 +726,11 @@ static PWINECRYPT_CERTSTORE CRYPT_MsgOpenStore(HCRYPTPROV hCryptProv,
     return store;
 }
 
-static PWINECRYPT_CERTSTORE CRYPT_PKCSOpenStore(HCRYPTPROV hCryptProv,
+static WINECRYPT_CERTSTORE *CRYPT_PKCSOpenStore(HCRYPTPROV hCryptProv,
  DWORD dwFlags, const void *pvPara)
 {
     HCRYPTMSG msg;
-    PWINECRYPT_CERTSTORE store = NULL;
+    WINECRYPT_CERTSTORE *store = NULL;
     const CRYPT_DATA_BLOB *data = pvPara;
     BOOL ret;
     DWORD msgOpenFlags = dwFlags & CERT_STORE_NO_CRYPT_RELEASE_FLAG ? 0 :
@@ -710,7 +767,7 @@ static PWINECRYPT_CERTSTORE CRYPT_PKCSOpenStore(HCRYPTPROV hCryptProv,
     return store;
 }
 
-static PWINECRYPT_CERTSTORE CRYPT_SerializedOpenStore(HCRYPTPROV hCryptProv,
+static WINECRYPT_CERTSTORE *CRYPT_SerializedOpenStore(HCRYPTPROV hCryptProv,
  DWORD dwFlags, const void *pvPara)
 {
     HCERTSTORE store;
@@ -735,10 +792,10 @@ static PWINECRYPT_CERTSTORE CRYPT_SerializedOpenStore(HCRYPTPROV hCryptProv,
         }
     }
     TRACE("returning %p\n", store);
-    return (PWINECRYPT_CERTSTORE)store;
+    return (WINECRYPT_CERTSTORE*)store;
 }
 
-static PWINECRYPT_CERTSTORE CRYPT_PhysOpenStoreW(HCRYPTPROV hCryptProv,
+static WINECRYPT_CERTSTORE *CRYPT_PhysOpenStoreW(HCRYPTPROV hCryptProv,
  DWORD dwFlags, const void *pvPara)
 {
     if (dwFlags & CERT_SYSTEM_STORE_RELOCATE_FLAG)
@@ -862,142 +919,10 @@ HCERTSTORE WINAPI CertOpenSystemStoreW(HCRYPTPROV_LEGACY hProv,
      CERT_SYSTEM_STORE_CURRENT_USER, szSubSystemProtocol);
 }
 
-#define CertContext_CopyProperties(to, from) \
- Context_CopyProperties((to), (from), sizeof(CERT_CONTEXT))
-
-BOOL WINAPI CertAddCertificateContextToStore(HCERTSTORE hCertStore,
- PCCERT_CONTEXT pCertContext, DWORD dwAddDisposition,
- PCCERT_CONTEXT *ppStoreContext)
-{
-    PWINECRYPT_CERTSTORE store = hCertStore;
-    BOOL ret = TRUE;
-    PCCERT_CONTEXT toAdd = NULL, existing = NULL;
-
-    TRACE("(%p, %p, %08x, %p)\n", hCertStore, pCertContext,
-     dwAddDisposition, ppStoreContext);
-
-    switch (dwAddDisposition)
-    {
-    case CERT_STORE_ADD_ALWAYS:
-        break;
-    case CERT_STORE_ADD_NEW:
-    case CERT_STORE_ADD_REPLACE_EXISTING:
-    case CERT_STORE_ADD_REPLACE_EXISTING_INHERIT_PROPERTIES:
-    case CERT_STORE_ADD_USE_EXISTING:
-    case CERT_STORE_ADD_NEWER:
-    case CERT_STORE_ADD_NEWER_INHERIT_PROPERTIES:
-    {
-        BYTE hashToAdd[20];
-        DWORD size = sizeof(hashToAdd);
-
-        ret = CertGetCertificateContextProperty(pCertContext, CERT_HASH_PROP_ID,
-         hashToAdd, &size);
-        if (ret)
-        {
-            CRYPT_HASH_BLOB blob = { sizeof(hashToAdd), hashToAdd };
-
-            existing = CertFindCertificateInStore(hCertStore,
-             pCertContext->dwCertEncodingType, 0, CERT_FIND_SHA1_HASH, &blob,
-             NULL);
-        }
-        break;
-    }
-    default:
-        FIXME("Unimplemented add disposition %d\n", dwAddDisposition);
-        SetLastError(E_INVALIDARG);
-        ret = FALSE;
-    }
-
-    switch (dwAddDisposition)
-    {
-    case CERT_STORE_ADD_ALWAYS:
-        toAdd = CertDuplicateCertificateContext(pCertContext);
-        break;
-    case CERT_STORE_ADD_NEW:
-        if (existing)
-        {
-            TRACE("found matching certificate, not adding\n");
-            SetLastError(CRYPT_E_EXISTS);
-            ret = FALSE;
-        }
-        else
-            toAdd = CertDuplicateCertificateContext(pCertContext);
-        break;
-    case CERT_STORE_ADD_REPLACE_EXISTING:
-        toAdd = CertDuplicateCertificateContext(pCertContext);
-        break;
-    case CERT_STORE_ADD_REPLACE_EXISTING_INHERIT_PROPERTIES:
-        toAdd = CertDuplicateCertificateContext(pCertContext);
-        if (existing)
-            CertContext_CopyProperties(toAdd, existing);
-        break;
-    case CERT_STORE_ADD_USE_EXISTING:
-        if (existing)
-        {
-            CertContext_CopyProperties(existing, pCertContext);
-            if (ppStoreContext)
-                *ppStoreContext = CertDuplicateCertificateContext(existing);
-        }
-        else
-            toAdd = CertDuplicateCertificateContext(pCertContext);
-        break;
-    case CERT_STORE_ADD_NEWER:
-        if (existing)
-        {
-            if (CompareFileTime(&existing->pCertInfo->NotBefore,
-             &pCertContext->pCertInfo->NotBefore) >= 0)
-            {
-                TRACE("existing certificate is newer, not adding\n");
-                SetLastError(CRYPT_E_EXISTS);
-                ret = FALSE;
-            }
-            else
-                toAdd = CertDuplicateCertificateContext(pCertContext);
-        }
-        else
-            toAdd = CertDuplicateCertificateContext(pCertContext);
-        break;
-    case CERT_STORE_ADD_NEWER_INHERIT_PROPERTIES:
-        if (existing)
-        {
-            if (CompareFileTime(&existing->pCertInfo->NotBefore,
-             &pCertContext->pCertInfo->NotBefore) >= 0)
-            {
-                TRACE("existing certificate is newer, not adding\n");
-                SetLastError(CRYPT_E_EXISTS);
-                ret = FALSE;
-            }
-            else
-            {
-                toAdd = CertDuplicateCertificateContext(pCertContext);
-                CertContext_CopyProperties(toAdd, existing);
-            }
-        }
-        else
-            toAdd = CertDuplicateCertificateContext(pCertContext);
-        break;
-    }
-
-    if (toAdd)
-    {
-        if (store)
-            ret = store->certs.addContext(store, (void *)toAdd,
-             (void *)existing, (const void **)ppStoreContext);
-        else if (ppStoreContext)
-            *ppStoreContext = CertDuplicateCertificateContext(toAdd);
-        CertFreeCertificateContext(toAdd);
-    }
-    CertFreeCertificateContext(existing);
-
-    TRACE("returning %d\n", ret);
-    return ret;
-}
-
-PCCERT_CONTEXT WINAPI CertEnumCertificatesInStore(HCERTSTORE hCertStore,
- PCCERT_CONTEXT pPrev)
+PCCERT_CONTEXT WINAPI CertEnumCertificatesInStore(HCERTSTORE hCertStore, PCCERT_CONTEXT pPrev)
 {
+    cert_t *prev = pPrev ? cert_from_ptr(pPrev) : NULL, *ret;
     WINECRYPT_CERTSTORE *hcs = hCertStore;
-    PCCERT_CONTEXT ret;
 
     TRACE("(%p, %p)\n", hCertStore, pPrev);
     if (!hCertStore)
@@ -1005,42 +930,32 @@ PCCERT_CONTEXT WINAPI CertEnumCertificatesInStore(HCERTSTORE hCertStore,
     else if (hcs->dwMagic != WINE_CRYPTCERTSTORE_MAGIC)
         ret = NULL;
     else
-        ret = (PCCERT_CONTEXT)hcs->certs.enumContext(hcs, (void *)pPrev);
-    return ret;
+        ret = (cert_t*)hcs->vtbl->certs.enumContext(hcs, prev ? &prev->base : NULL);
+    return ret ? &ret->ctx : NULL;
 }
 
 BOOL WINAPI CertDeleteCertificateFromStore(PCCERT_CONTEXT pCertContext)
 {
-    BOOL ret;
+    WINECRYPT_CERTSTORE *hcs;
 
     TRACE("(%p)\n", pCertContext);
 
     if (!pCertContext)
-        ret = TRUE;
-    else if (!pCertContext->hCertStore)
-        ret = CertFreeCertificateContext(pCertContext);
-    else
-    {
-        PWINECRYPT_CERTSTORE hcs = pCertContext->hCertStore;
+        return TRUE;
 
-        if (hcs->dwMagic != WINE_CRYPTCERTSTORE_MAGIC)
-            ret = FALSE;
-        else
-            ret = hcs->certs.deleteContext(hcs, (void *)pCertContext);
-        if (ret)
-            ret = CertFreeCertificateContext(pCertContext);
-    }
-    return ret;
-}
+    hcs = pCertContext->hCertStore;
 
-#define CrlContext_CopyProperties(to, from) \
- Context_CopyProperties((to), (from), sizeof(CRL_CONTEXT))
+    if (hcs->dwMagic != WINE_CRYPTCERTSTORE_MAGIC)
+        return FALSE;
+
+    return hcs->vtbl->certs.delete(hcs, &cert_from_ptr(pCertContext)->base);
+}
 
 BOOL WINAPI CertAddCRLContextToStore(HCERTSTORE hCertStore,
  PCCRL_CONTEXT pCrlContext, DWORD dwAddDisposition,
  PCCRL_CONTEXT* ppStoreContext)
 {
-    PWINECRYPT_CERTSTORE store = hCertStore;
+    WINECRYPT_CERTSTORE *store = hCertStore;
     BOOL ret = TRUE;
     PCCRL_CONTEXT toAdd = NULL, existing = NULL;
 
@@ -1101,7 +1016,7 @@ BOOL WINAPI CertAddCRLContextToStore(HCERTSTORE hCertStore,
             if (newer < 0)
             {
                 toAdd = CertDuplicateCRLContext(pCrlContext);
-                CrlContext_CopyProperties(toAdd, existing);
+                Context_CopyProperties(toAdd, existing);
             }
             else
             {
@@ -1119,12 +1034,12 @@ BOOL WINAPI CertAddCRLContextToStore(HCERTSTORE hCertStore,
     case CERT_STORE_ADD_REPLACE_EXISTING_INHERIT_PROPERTIES:
         toAdd = CertDuplicateCRLContext(pCrlContext);
         if (existing)
-            CrlContext_CopyProperties(toAdd, existing);
+            Context_CopyProperties(toAdd, existing);
         break;
     case CERT_STORE_ADD_USE_EXISTING:
         if (existing)
         {
-            CrlContext_CopyProperties(existing, pCrlContext);
+            Context_CopyProperties(existing, pCrlContext);
             if (ppStoreContext)
                 *ppStoreContext = CertDuplicateCRLContext(existing);
         }
@@ -1138,14 +1053,19 @@ BOOL WINAPI CertAddCRLContextToStore(HCERTSTORE hCertStore,
 
     if (toAdd)
     {
-        if (store)
-            ret = store->crls.addContext(store, (void *)toAdd,
-             (void *)existing, (const void **)ppStoreContext);
-        else if (ppStoreContext)
+        if (store) {
+            context_t *ret_context;
+            ret = store->vtbl->crls.addContext(store, context_from_ptr(toAdd),
+             existing ? context_from_ptr(existing) : NULL, ppStoreContext ? &ret_context : NULL, FALSE);
+            if (ret && ppStoreContext)
+                *ppStoreContext = context_ptr(ret_context);
+        }else if (ppStoreContext) {
             *ppStoreContext = CertDuplicateCRLContext(toAdd);
+        }
         CertFreeCRLContext(toAdd);
     }
-    CertFreeCRLContext(existing);
+    if (existing)
+        CertFreeCRLContext(existing);
 
     TRACE("returning %d\n", ret);
     return ret;
@@ -1153,33 +1073,29 @@ BOOL WINAPI CertAddCRLContextToStore(HCERTSTORE hCertStore,
 
 BOOL WINAPI CertDeleteCRLFromStore(PCCRL_CONTEXT pCrlContext)
 {
+    WINECRYPT_CERTSTORE *hcs;
     BOOL ret;
 
     TRACE("(%p)\n", pCrlContext);
 
     if (!pCrlContext)
-        ret = TRUE;
-    else if (!pCrlContext->hCertStore)
-        ret = CertFreeCRLContext(pCrlContext);
-    else
-    {
-        PWINECRYPT_CERTSTORE hcs = pCrlContext->hCertStore;
+        return TRUE;
 
-        if (hcs->dwMagic != WINE_CRYPTCERTSTORE_MAGIC)
-            ret = FALSE;
-        else
-            ret = hcs->crls.deleteContext(hcs, (void *)pCrlContext);
-        if (ret)
-            ret = CertFreeCRLContext(pCrlContext);
-    }
+    hcs = pCrlContext->hCertStore;
+
+    if (hcs->dwMagic != WINE_CRYPTCERTSTORE_MAGIC)
+        return FALSE;
+
+    ret = hcs->vtbl->crls.delete(hcs, &crl_from_ptr(pCrlContext)->base);
+    if (ret)
+        ret = CertFreeCRLContext(pCrlContext);
     return ret;
 }
 
-PCCRL_CONTEXT WINAPI CertEnumCRLsInStore(HCERTSTORE hCertStore,
- PCCRL_CONTEXT pPrev)
+PCCRL_CONTEXT WINAPI CertEnumCRLsInStore(HCERTSTORE hCertStore, PCCRL_CONTEXT pPrev)
 {
+    crl_t *ret, *prev = pPrev ? crl_from_ptr(pPrev) : NULL;
     WINECRYPT_CERTSTORE *hcs = hCertStore;
-    PCCRL_CONTEXT ret;
 
     TRACE("(%p, %p)\n", hCertStore, pPrev);
     if (!hCertStore)
@@ -1187,8 +1103,8 @@ PCCRL_CONTEXT WINAPI CertEnumCRLsInStore(HCERTSTORE hCertStore,
     else if (hcs->dwMagic != WINE_CRYPTCERTSTORE_MAGIC)
         ret = NULL;
     else
-        ret = (PCCRL_CONTEXT)hcs->crls.enumContext(hcs, (void *)pPrev);
-    return ret;
+        ret = (crl_t*)hcs->vtbl->crls.enumContext(hcs, prev ? &prev->base : NULL);
+    return ret ? &ret->ctx : NULL;
 }
 
 HCERTSTORE WINAPI CertDuplicateStore(HCERTSTORE hCertStore)
@@ -1198,13 +1114,14 @@ HCERTSTORE WINAPI CertDuplicateStore(HCERTSTORE hCertStore)
     TRACE("(%p)\n", hCertStore);
 
     if (hcs && hcs->dwMagic == WINE_CRYPTCERTSTORE_MAGIC)
-        InterlockedIncrement(&hcs->ref);
+        hcs->vtbl->addref(hcs);
     return hCertStore;
 }
 
 BOOL WINAPI CertCloseStore(HCERTSTORE hCertStore, DWORD dwFlags)
 {
     WINECRYPT_CERTSTORE *hcs = hCertStore;
+    DWORD res;
 
     TRACE("(%p, %08x)\n", hCertStore, dwFlags);
 
@@ -1214,16 +1131,12 @@ BOOL WINAPI CertCloseStore(HCERTSTORE hCertStore, DWORD dwFlags)
     if ( hcs->dwMagic != WINE_CRYPTCERTSTORE_MAGIC )
         return FALSE;
 
-    if (hcs->ref <= 0)
-        ERR("%p's ref count is %d\n", hcs, hcs->ref);
-    if (InterlockedDecrement(&hcs->ref) == 0)
-    {
-        TRACE("%p's ref count is 0, freeing\n", hcs);
-        hcs->dwMagic = 0;
-        hcs->closeStore(hcs, dwFlags);
+    res = hcs->vtbl->release(hcs, dwFlags);
+    if (res != ERROR_SUCCESS) {
+        SetLastError(res);
+        return FALSE;
     }
-    else
-        TRACE("%p's ref count is %d\n", hcs, hcs->ref);
+
     return TRUE;
 }
 
@@ -1242,8 +1155,8 @@ BOOL WINAPI CertControlStore(HCERTSTORE hCertStore, DWORD dwFlags,
         ret = FALSE;
     else
     {
-        if (hcs->control)
-            ret = hcs->control(hCertStore, dwFlags, dwCtrlType, pvCtrlPara);
+        if (hcs->vtbl->control)
+            ret = hcs->vtbl->control(hcs, dwFlags, dwCtrlType, pvCtrlPara);
         else
             ret = TRUE;
     }
@@ -1253,7 +1166,7 @@ BOOL WINAPI CertControlStore(HCERTSTORE hCertStore, DWORD dwFlags,
 BOOL WINAPI CertGetStoreProperty(HCERTSTORE hCertStore, DWORD dwPropId,
  void *pvData, DWORD *pcbData)
 {
-    PWINECRYPT_CERTSTORE store = hCertStore;
+    WINECRYPT_CERTSTORE *store = hCertStore;
     BOOL ret = FALSE;
 
     TRACE("(%p, %d, %p, %p)\n", hCertStore, dwPropId, pvData, pcbData);
@@ -1317,7 +1230,7 @@ BOOL WINAPI CertGetStoreProperty(HCERTSTORE hCertStore, DWORD dwPropId,
 BOOL WINAPI CertSetStoreProperty(HCERTSTORE hCertStore, DWORD dwPropId,
  DWORD dwFlags, const void *pvData)
 {
-    PWINECRYPT_CERTSTORE store = hCertStore;
+    WINECRYPT_CERTSTORE *store = hCertStore;
     BOOL ret = FALSE;
 
     TRACE("(%p, %d, %08x, %p)\n", hCertStore, dwPropId, dwFlags, pvData);
@@ -1463,3 +1376,81 @@ BOOL WINAPI CertRegisterPhysicalStore(const void *pvSystemStore, DWORD dwFlags,
          dwFlags, debugstr_w(pwszStoreName), pStoreInfo, pvReserved);
     return FALSE;
 }
+
+static void EmptyStore_addref(WINECRYPT_CERTSTORE *store)
+{
+    TRACE("(%p)\n", store);
+}
+
+static DWORD EmptyStore_release(WINECRYPT_CERTSTORE *store, DWORD flags)
+{
+    TRACE("(%p)\n", store);
+    return E_UNEXPECTED;
+}
+
+static void EmptyStore_releaseContext(WINECRYPT_CERTSTORE *store, context_t *context)
+{
+    Context_Free(context);
+}
+
+static BOOL EmptyStore_add(WINECRYPT_CERTSTORE *store, context_t *context,
+ context_t *replace, context_t **ret_context, BOOL use_link)
+{
+    TRACE("(%p, %p, %p, %p)\n", store, context, replace, ret_context);
+
+    /* FIXME: We should clone the context */
+    if(ret_context) {
+        Context_AddRef(context);
+        *ret_context = context;
+    }
+
+    return TRUE;
+}
+
+static context_t *EmptyStore_enum(WINECRYPT_CERTSTORE *store, context_t *prev)
+{
+    TRACE("(%p, %p)\n", store, prev);
+
+    SetLastError(CRYPT_E_NOT_FOUND);
+    return NULL;
+}
+
+static BOOL EmptyStore_delete(WINECRYPT_CERTSTORE *store, context_t *context)
+{
+    return TRUE;
+}
+
+static BOOL EmptyStore_control(WINECRYPT_CERTSTORE *store, DWORD flags, DWORD ctrl_type, void const *ctrl_para)
+{
+    TRACE("()\n");
+
+    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+    return FALSE;
+}
+
+static const store_vtbl_t EmptyStoreVtbl = {
+    EmptyStore_addref,
+    EmptyStore_release,
+    EmptyStore_releaseContext,
+    EmptyStore_control,
+    {
+        EmptyStore_add,
+        EmptyStore_enum,
+        EmptyStore_delete
+    }, {
+        EmptyStore_add,
+        EmptyStore_enum,
+        EmptyStore_delete
+    }, {
+        EmptyStore_add,
+        EmptyStore_enum,
+        EmptyStore_delete
+    }
+};
+
+WINECRYPT_CERTSTORE empty_store;
+
+void init_empty_store(void)
+{
+    CRYPT_InitStore(&empty_store, CERT_STORE_READONLY_FLAG, StoreTypeEmpty, &EmptyStoreVtbl);
+}
index 5974d4c..f58927a 100644 (file)
@@ -448,7 +448,7 @@ DWORD WINAPI CertNameToStrA(DWORD dwCertEncodingType, PCERT_NAME_BLOB pName,
             for (j = 0; (!psz || ret < csz) && j < rdn->cRDNAttr; j++)
             {
                 DWORD chars;
-                char prefixBuf[10]; /* big enough for GivenName */
+                char prefixBuf[13]; /* big enough for SERIALNUMBER */
                 LPCSTR prefix = NULL;
 
                 if ((dwStrType & 0x000000ff) == CERT_OID_NAME_STR)
index 271a312..ad06b52 100644 (file)
@@ -64,7 +64,7 @@ reactos/dll/win32/comctl32         # Synced to Wine 1.7.17
 reactos/dll/win32/comdlg32         # Synced to Wine 1.7.17
 reactos/dll/win32/compstui         # Synced to Wine-1.7.1
 reactos/dll/win32/credui           # Synced to Wine-1.7.1
-reactos/dll/win32/crypt32          # Synced to Wine-1.7.1
+reactos/dll/win32/crypt32          # Synced to Wine-1.7.17
 reactos/dll/win32/cryptdlg         # Synced to Wine-1.7.1
 reactos/dll/win32/cryptdll         # Synced to Wine-1.7.1
 reactos/dll/win32/cryptnet         # Synced to Wine-1.7.1