crypt32: Move context properties to a separate file.
This commit is contained in:
parent
2eca872675
commit
91b80fc8e2
|
@ -11,6 +11,7 @@ C_SRCS = \
|
|||
cert.c \
|
||||
encode.c \
|
||||
oid.c \
|
||||
proplist.c \
|
||||
protectdata.c \
|
||||
serialize.c \
|
||||
store.c \
|
||||
|
|
|
@ -41,4 +41,31 @@ void crypt_oid_free(void);
|
|||
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
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -182,27 +182,19 @@ typedef struct WINE_CRYPTCERTSTORE
|
|||
*/
|
||||
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 @@ static WINECRYPT_CERTSTORE *CRYPT_MemOpenStore(HCRYPTPROV hCryptProv,
|
|||
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 @@ static PWINE_CERT_CONTEXT CRYPT_CreateCertificateContext(
|
|||
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 @@ end:
|
|||
|
||||
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 @@ PCCERT_CONTEXT WINAPI CertCreateCertificateContext(DWORD dwCertEncodingType,
|
|||
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 CRYPT_GetCertHashProp(PWINE_CERT_CONTEXT context, DWORD dwPropId,
|
|||
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 @@ static BOOL WINAPI CRYPT_GetCertificateContextProperty(
|
|||
SetLastError(CRYPT_E_NOT_FOUND);
|
||||
}
|
||||
}
|
||||
LeaveCriticalSection(&context->cs);
|
||||
TRACE("returning %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
@ -2134,65 +2075,6 @@ BOOL WINAPI CertGetCertificateContextProperty(PCCERT_CONTEXT pCertContext,
|
|||
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 @@ static BOOL WINAPI CRYPT_SetCertificateContextProperty(
|
|||
|
||||
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 @@ static BOOL WINAPI CRYPT_SetCertificateContextProperty(
|
|||
{
|
||||
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 @@ BOOL WINAPI CertAddCertificateContextToStore(HCERTSTORE hCertStore,
|
|||
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);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue