216 lines
5.5 KiB
C
216 lines
5.5 KiB
C
/*
|
|
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, 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, %d, %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;
|
|
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);
|
|
break;
|
|
}
|
|
}
|
|
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);
|
|
}
|