crypt32: Move context properties to a separate file.
diff --git a/dlls/crypt32/Makefile.in b/dlls/crypt32/Makefile.in
index 9338b31..e107292 100644
--- a/dlls/crypt32/Makefile.in
+++ b/dlls/crypt32/Makefile.in
@@ -11,6 +11,7 @@
 	cert.c \
 	encode.c \
 	oid.c \
+	proplist.c \
 	protectdata.c \
 	serialize.c \
 	store.c \
diff --git a/dlls/crypt32/crypt32_private.h b/dlls/crypt32/crypt32_private.h
index ee0228c..25c41e4 100644
--- a/dlls/crypt32/crypt32_private.h
+++ b/dlls/crypt32/crypt32_private.h
@@ -41,4 +41,31 @@
 const void *CRYPT_ReadSerializedElement(const BYTE *pbElement,
  DWORD cbElement, DWORD dwContextTypeFlags, DWORD *pdwContentType);
 
+/**
+ *  Context property list functions
+ */
+struct _CONTEXT_PROPERTY_LIST;
+typedef struct _CONTEXT_PROPERTY_LIST *PCONTEXT_PROPERTY_LIST;
+
+PCONTEXT_PROPERTY_LIST ContextPropertyList_Create(void);
+
+/* 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,
+ PCRYPT_DATA_BLOB blob);
+
+BOOL ContextPropertyList_SetProperty(PCONTEXT_PROPERTY_LIST list, DWORD id,
+ const BYTE *pbData, size_t cbData);
+
+void ContextPropertyList_RemoveProperty(PCONTEXT_PROPERTY_LIST list, DWORD id);
+
+DWORD ContextPropertyList_EnumPropIDs(PCONTEXT_PROPERTY_LIST list, DWORD id);
+
+void ContextPropertyList_Copy(PCONTEXT_PROPERTY_LIST to,
+ PCONTEXT_PROPERTY_LIST from);
+
+void ContextPropertyList_Free(PCONTEXT_PROPERTY_LIST list);
+
 #endif
diff --git a/dlls/crypt32/proplist.c b/dlls/crypt32/proplist.c
new file mode 100644
index 0000000..ec9e242
--- /dev/null
+++ b/dlls/crypt32/proplist.c
@@ -0,0 +1,215 @@
+/*
+ * Copyright 2004-2006 Juan Lang
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#include <assert.h>
+#include <stdarg.h>
+#include "windef.h"
+#include "winbase.h"
+#include "wincrypt.h"
+#include "wine/debug.h"
+#include "wine/list.h"
+#include "crypt32_private.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(crypt);
+
+typedef struct _CONTEXT_PROPERTY_LIST
+{
+    CRITICAL_SECTION cs;
+    struct list      properties;
+} CONTEXT_PROPERTY_LIST;
+
+typedef struct _CONTEXT_PROPERTY
+{
+    DWORD       propID;
+    DWORD       cbData;
+    LPBYTE      pbData;
+    struct list entry;
+} CONTEXT_PROPERTY, *PCONTEXT_PROPERTY;
+
+PCONTEXT_PROPERTY_LIST ContextPropertyList_Create(void)
+{
+    PCONTEXT_PROPERTY_LIST list = CryptMemAlloc(sizeof(CONTEXT_PROPERTY_LIST));
+
+    if (list)
+    {
+        InitializeCriticalSection(&list->cs);
+        list_init(&list->properties);
+    }
+    return list;
+}
+
+void ContextPropertyList_Free(PCONTEXT_PROPERTY_LIST list)
+{
+    PCONTEXT_PROPERTY prop, next;
+
+    LIST_FOR_EACH_ENTRY_SAFE(prop, next, &list->properties, CONTEXT_PROPERTY,
+     entry)
+    {
+        list_remove(&prop->entry);
+        CryptMemFree(prop->pbData);
+        CryptMemFree(prop);
+    }
+    DeleteCriticalSection(&list->cs);
+    CryptMemFree(list);
+}
+
+BOOL ContextPropertyList_FindProperty(PCONTEXT_PROPERTY_LIST list, DWORD id,
+ PCRYPT_DATA_BLOB blob)
+{
+    PCONTEXT_PROPERTY prop;
+    BOOL ret = FALSE;
+
+    TRACE("(%p, %ld, %p)\n", list, id, blob);
+
+    EnterCriticalSection(&list->cs);
+    LIST_FOR_EACH_ENTRY(prop, &list->properties, CONTEXT_PROPERTY, entry)
+    {
+        if (prop->propID == id)
+        {
+            blob->cbData = prop->cbData;
+            blob->pbData = prop->pbData;
+            ret = TRUE;
+            break;
+        }
+    }
+    LeaveCriticalSection(&list->cs);
+    return ret;
+}
+
+BOOL ContextPropertyList_SetProperty(PCONTEXT_PROPERTY_LIST list, DWORD id,
+ const BYTE *pbData, size_t cbData)
+{
+    LPBYTE data;
+    BOOL ret = FALSE;
+
+    if (cbData)
+    {
+        data = CryptMemAlloc(cbData);
+        if (data)
+            memcpy(data, pbData, cbData);
+    }
+    else
+        data = NULL;
+    if (!cbData || data)
+    {
+        PCONTEXT_PROPERTY prop;
+        BOOL found = FALSE;
+
+        EnterCriticalSection(&list->cs);
+        LIST_FOR_EACH_ENTRY(prop, &list->properties, CONTEXT_PROPERTY, entry)
+        {
+            if (prop->propID == id)
+            {
+                found = TRUE;
+                break;
+            }
+        }
+        if (found)
+        {
+            CryptMemFree(prop->pbData);
+            prop->cbData = cbData;
+            prop->pbData = data;
+            ret = TRUE;
+        }
+        else
+        {
+            prop = CryptMemAlloc(sizeof(CONTEXT_PROPERTY));
+            if (prop)
+            {
+                prop->propID = id;
+                prop->cbData = cbData;
+                list_init(&prop->entry);
+                prop->pbData = data;
+                list_add_tail(&list->properties, &prop->entry);
+                ret = TRUE;
+            }
+            else
+                CryptMemFree(data);
+        }
+        LeaveCriticalSection(&list->cs);
+    }
+    return ret;
+}
+
+void ContextPropertyList_RemoveProperty(PCONTEXT_PROPERTY_LIST list, DWORD id)
+{
+    PCONTEXT_PROPERTY prop, next;
+
+    EnterCriticalSection(&list->cs);
+    LIST_FOR_EACH_ENTRY_SAFE(prop, next, &list->properties, CONTEXT_PROPERTY,
+     entry)
+    {
+        if (prop->propID == id)
+        {
+            list_remove(&prop->entry);
+            CryptMemFree(prop->pbData);
+            CryptMemFree(prop);
+        }
+    }
+    LeaveCriticalSection(&list->cs);
+}
+
+/* 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 ret;
+
+    EnterCriticalSection(&list->cs);
+    if (id)
+    {
+        PCONTEXT_PROPERTY cursor = NULL;
+
+        LIST_FOR_EACH_ENTRY(cursor, &list->properties, CONTEXT_PROPERTY, entry)
+        {
+            if (cursor->propID == id)
+                break;
+        }
+        if (cursor)
+        {
+            if (cursor->entry.next != &list->properties)
+                ret = LIST_ENTRY(cursor->entry.next, CONTEXT_PROPERTY,
+                 entry)->propID;
+            else
+                ret = 0;
+        }
+        else
+            ret = 0;
+    }
+    else if (!list_empty(&list->properties))
+        ret = LIST_ENTRY(list->properties.next, CONTEXT_PROPERTY,
+         entry)->propID;
+    else
+        ret = 0;
+    LeaveCriticalSection(&list->cs);
+    return ret;
+}
+
+void ContextPropertyList_Copy(PCONTEXT_PROPERTY_LIST to,
+ PCONTEXT_PROPERTY_LIST from)
+{
+    PCONTEXT_PROPERTY prop;
+
+    EnterCriticalSection(&from->cs);
+    LIST_FOR_EACH_ENTRY(prop, &from->properties, CONTEXT_PROPERTY, entry)
+    {
+        ContextPropertyList_SetProperty(to, prop->propID, prop->pbData,
+         prop->cbData);
+    }
+    LeaveCriticalSection(&from->cs);
+}
diff --git a/dlls/crypt32/store.c b/dlls/crypt32/store.c
index fe37a56..92f3ee6 100644
--- a/dlls/crypt32/store.c
+++ b/dlls/crypt32/store.c
@@ -182,27 +182,19 @@
  */
 typedef struct _WINE_CERT_CONTEXT
 {
-    CERT_CONTEXT     cert;
-    LONG             ref;
-    CRITICAL_SECTION cs;
-    struct list      extendedProperties;
+    CERT_CONTEXT           cert;
+    LONG                   ref;
+    PCONTEXT_PROPERTY_LIST properties;
 } WINE_CERT_CONTEXT, *PWINE_CERT_CONTEXT;
+typedef const struct _WINE_CERT_CONTEXT PCWINE_CERT_CONTEXT;
 
 typedef struct _WINE_CERT_CONTEXT_REF
 {
     CERT_CONTEXT       cert;
     LONG               ref;
-    WINE_CERT_CONTEXT *context;
+    PWINE_CERT_CONTEXT context;
 } WINE_CERT_CONTEXT_REF, *PWINE_CERT_CONTEXT_REF;
-
-/* Stores an extended property in a cert. */
-typedef struct _WINE_CERT_PROPERTY
-{
-    DWORD       propID;
-    DWORD       cbData;
-    LPBYTE      pbData;
-    struct list entry;
-} WINE_CERT_PROPERTY, *PWINE_CERT_PROPERTY;
+typedef const struct _WINE_CERT_CONTEXT_REF PCWINE_CERT_CONTEXT_REF;
 
 /* A mem store has a list of these.  They're also returned by the mem store
  * during enumeration.
@@ -554,7 +546,6 @@
             store->hdr.addCert       = CRYPT_MemAddCert;
             store->hdr.enumCert      = CRYPT_MemEnumCert;
             store->hdr.deleteCert    = CRYPT_MemDeleteCert;
-            store->hdr.freeCert      = NULL;
             store->hdr.control       = NULL;
             InitializeCriticalSection(&store->cs);
             list_init(&store->certs);
@@ -1905,8 +1896,7 @@
         cert->cert.pCertInfo          = certInfo;
         cert->cert.hCertStore         = 0;
         cert->ref = 0;
-        InitializeCriticalSection(&cert->cs);
-        list_init(&cert->extendedProperties);
+        cert->properties = ContextPropertyList_Create();
     }
 
 end:
@@ -1915,18 +1905,9 @@
 
 static void CRYPT_FreeCert(PWINE_CERT_CONTEXT context)
 {
-    PWINE_CERT_PROPERTY prop, next;
-
     CryptMemFree(context->cert.pbCertEncoded);
     LocalFree(context->cert.pCertInfo);
-    DeleteCriticalSection(&context->cs);
-    LIST_FOR_EACH_ENTRY_SAFE(prop, next, &context->extendedProperties,
-     WINE_CERT_PROPERTY, entry)
-    {
-        list_remove(&prop->entry);
-        CryptMemFree(prop->pbData);
-        CryptMemFree(prop);
-    }
+    ContextPropertyList_Free(context->properties);
     CryptMemFree(context);
 }
 
@@ -1946,46 +1927,14 @@
     return (PCCERT_CONTEXT)ret;
 }
 
-/* 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 WINAPI CertEnumCertificateContextProperties(PCCERT_CONTEXT pCertContext,
  DWORD dwPropId)
 {
     PWINE_CERT_CONTEXT_REF ref = (PWINE_CERT_CONTEXT_REF)pCertContext;
-    DWORD ret;
 
     TRACE("(%p, %ld)\n", pCertContext, dwPropId);
 
-    EnterCriticalSection(&ref->context->cs);
-    if (dwPropId)
-    {
-        PWINE_CERT_PROPERTY cursor = NULL;
-
-        LIST_FOR_EACH_ENTRY(cursor, &ref->context->extendedProperties,
-         WINE_CERT_PROPERTY, entry)
-        {
-            if (cursor->propID == dwPropId)
-                break;
-        }
-        if (cursor)
-        {
-            if (cursor->entry.next != &ref->context->extendedProperties)
-                ret = LIST_ENTRY(cursor->entry.next, WINE_CERT_PROPERTY,
-                 entry)->propID;
-            else
-                ret = 0;
-        }
-        else
-            ret = 0;
-    }
-    else if (!list_empty(&ref->context->extendedProperties))
-        ret = LIST_ENTRY(ref->context->extendedProperties.next,
-         WINE_CERT_PROPERTY, entry)->propID;
-    else
-        ret = 0;
-    LeaveCriticalSection(&ref->context->cs);
-    return ret;
+    return ContextPropertyList_EnumPropIDs(ref->context->properties, dwPropId);
 }
 
 static BOOL CRYPT_GetCertHashProp(PWINE_CERT_CONTEXT context, DWORD dwPropId,
@@ -2007,40 +1956,33 @@
 static BOOL WINAPI CRYPT_GetCertificateContextProperty(
  PWINE_CERT_CONTEXT context, DWORD dwPropId, void *pvData, DWORD *pcbData)
 {
-    PWINE_CERT_PROPERTY prop;
-    BOOL ret, found;
+    BOOL ret;
+    CRYPT_DATA_BLOB blob;
 
     TRACE("(%p, %ld, %p, %p)\n", context, dwPropId, pvData, pcbData);
 
-    EnterCriticalSection(&context->cs);
-    ret = FALSE;
-    found = FALSE;
-    LIST_FOR_EACH_ENTRY(prop, &context->extendedProperties,
-     WINE_CERT_PROPERTY, entry)
+    ret = ContextPropertyList_FindProperty(context->properties, dwPropId,
+     &blob);
+    if (ret)
     {
-        if (prop->propID == dwPropId)
+        if (!pvData)
         {
-            if (!pvData)
-            {
-                *pcbData = prop->cbData;
-                ret = TRUE;
-            }
-            else if (*pcbData < prop->cbData)
-            {
-                SetLastError(ERROR_MORE_DATA);
-                *pcbData = prop->cbData;
-            }
-            else
-            {
-                memcpy(pvData, prop->pbData, prop->cbData);
-                *pcbData = prop->cbData;
-                ret = TRUE;
-            }
-            found = TRUE;
-            break;
+            *pcbData = blob.cbData;
+            ret = TRUE;
+        }
+        else if (*pcbData < blob.cbData)
+        {
+            SetLastError(ERROR_MORE_DATA);
+            *pcbData = blob.cbData;
+        }
+        else
+        {
+            memcpy(pvData, blob.pbData, blob.cbData);
+            *pcbData = blob.cbData;
+            ret = TRUE;
         }
     }
-    if (!found)
+    else
     {
         /* Implicit properties */
         switch (dwPropId)
@@ -2076,7 +2018,6 @@
             SetLastError(CRYPT_E_NOT_FOUND);
         }
     }
-    LeaveCriticalSection(&context->cs);
     TRACE("returning %d\n", ret);
     return ret;
 }
@@ -2134,65 +2075,6 @@
     return ret;
 }
 
-/* Copies cbData bytes from pbData to the context's property with ID
- * dwPropId.
- */
-static BOOL CRYPT_SaveCertificateContextProperty(PWINE_CERT_CONTEXT context,
- DWORD dwPropId, const BYTE *pbData, size_t cbData)
-{
-    BOOL ret = FALSE;
-    LPBYTE data;
-
-    if (cbData)
-    {
-        data = CryptMemAlloc(cbData);
-        if (data)
-            memcpy(data, pbData, cbData);
-    }
-    else
-        data = NULL;
-    if (!cbData || data)
-    {
-        PWINE_CERT_PROPERTY prop;
-        BOOL found = FALSE;
-
-        EnterCriticalSection(&context->cs);
-        LIST_FOR_EACH_ENTRY(prop, &context->extendedProperties,
-         WINE_CERT_PROPERTY, entry)
-        {
-            if (prop->propID == dwPropId)
-            {
-                found = TRUE;
-                break;
-            }
-        }
-        if (found)
-        {
-            CryptMemFree(prop->pbData);
-            prop->cbData = cbData;
-            prop->pbData = data;
-            ret = TRUE;
-        }
-        else
-        {
-            prop = CryptMemAlloc(sizeof(WINE_CERT_PROPERTY));
-            if (prop)
-            {
-                prop->propID = dwPropId;
-                prop->cbData = cbData;
-                list_init(&prop->entry);
-                prop->pbData = data;
-                list_add_tail(&context->extendedProperties, &prop->entry);
-                ret = TRUE;
-            }
-            else
-                CryptMemFree(data);
-        }
-        LeaveCriticalSection(&context->cs);
-    }
-    return ret;
-}
-
 static BOOL WINAPI CRYPT_SetCertificateContextProperty(
  PWINE_CERT_CONTEXT context, DWORD dwPropId, DWORD dwFlags, const void *pvData)
 {
@@ -2202,20 +2084,7 @@
 
     if (!pvData)
     {
-        PWINE_CERT_PROPERTY prop, next;
-
-        EnterCriticalSection(&context->cs);
-        LIST_FOR_EACH_ENTRY_SAFE(prop, next, &context->extendedProperties,
-         WINE_CERT_PROPERTY, entry)
-        {
-            if (prop->propID == dwPropId)
-            {
-                list_remove(&prop->entry);
-                CryptMemFree(prop->pbData);
-                CryptMemFree(prop);
-            }
-        }
-        LeaveCriticalSection(&context->cs);
+        ContextPropertyList_RemoveProperty(context->properties, dwPropId);
         ret = TRUE;
     }
     else
@@ -2242,12 +2111,12 @@
         {
             PCRYPT_DATA_BLOB blob = (PCRYPT_DATA_BLOB)pvData;
 
-            ret = CRYPT_SaveCertificateContextProperty(context, dwPropId,
+            ret = ContextPropertyList_SetProperty(context->properties, dwPropId,
              blob->pbData, blob->cbData);
             break;
         }
         case CERT_DATE_STAMP_PROP_ID:
-            ret = CRYPT_SaveCertificateContextProperty(context, dwPropId,
+            ret = ContextPropertyList_SetProperty(context->properties, dwPropId,
              pvData, sizeof(FILETIME));
             break;
         default:
@@ -2319,51 +2188,12 @@
         return FALSE;
     }
 
-    cert = CRYPT_CreateCertificateContext(ref->context->cert.dwCertEncodingType,
-     ref->context->cert.pbCertEncoded, ref->context->cert.cbCertEncoded);
+    cert = CRYPT_CreateCertificateContext(ref->cert.dwCertEncodingType,
+     ref->cert.pbCertEncoded, ref->cert.cbCertEncoded);
     if (cert)
     {
-        DWORD prop = 0, bufSize = 0;
-        LPBYTE buf = NULL;
-
-        ret = TRUE;
-        EnterCriticalSection(&ref->context->cs);
-        do {
-            prop = CertEnumCertificateContextProperties((PCCERT_CONTEXT)ref,
-             prop);
-            if (prop)
-            {
-                DWORD propSize = 0;
-
-                ret = CertGetCertificateContextProperty(pCertContext, prop,
-                 NULL, &propSize);
-                if (ret)
-                {
-                    if (bufSize < propSize)
-                    {
-                        if (buf)
-                            buf = CryptMemRealloc(buf, propSize);
-                        else
-                            buf = CryptMemAlloc(propSize);
-                        bufSize = propSize;
-                    }
-                    if (buf)
-                    {
-                        ret = CertGetCertificateContextProperty(pCertContext,
-                         prop, buf, &propSize);
-                        if (ret)
-                            ret = CRYPT_SaveCertificateContextProperty(cert,
-                             prop, buf, bufSize);
-                    }
-                    else
-                        ret = FALSE;
-                }
-            }
-        } while (ret && prop != 0);
-        CryptMemFree(buf);
-        LeaveCriticalSection(&ref->context->cs);
-        if (ret)
-            ret = store->addCert(store, cert, dwAddDisposition, ppStoreContext);
+        ContextPropertyList_Copy(cert->properties, ref->context->properties);
+        ret = store->addCert(store, cert, dwAddDisposition, ppStoreContext);
         if (!ret)
             CRYPT_FreeCert(cert);
     }