wine/dlls/crypt32/proplist.c
2013-09-04 14:38:27 +02:00

217 lines
5.6 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);
struct _CONTEXT_PROPERTY_LIST
{
CRITICAL_SECTION cs;
struct list properties;
};
typedef struct _CONTEXT_PROPERTY
{
DWORD propID;
DWORD cbData;
LPBYTE pbData;
struct list entry;
} CONTEXT_PROPERTY;
CONTEXT_PROPERTY_LIST *ContextPropertyList_Create(void)
{
CONTEXT_PROPERTY_LIST *list = CryptMemAlloc(sizeof(CONTEXT_PROPERTY_LIST));
if (list)
{
InitializeCriticalSection(&list->cs);
list->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": PCONTEXT_PROPERTY_LIST->cs");
list_init(&list->properties);
}
return list;
}
void ContextPropertyList_Free(CONTEXT_PROPERTY_LIST *list)
{
CONTEXT_PROPERTY *prop, *next;
LIST_FOR_EACH_ENTRY_SAFE(prop, next, &list->properties, CONTEXT_PROPERTY,
entry)
{
list_remove(&prop->entry);
CryptMemFree(prop->pbData);
CryptMemFree(prop);
}
list->cs.DebugInfo->Spare[0] = 0;
DeleteCriticalSection(&list->cs);
CryptMemFree(list);
}
BOOL ContextPropertyList_FindProperty(CONTEXT_PROPERTY_LIST *list, DWORD id,
PCRYPT_DATA_BLOB blob)
{
CONTEXT_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(CONTEXT_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)
{
CONTEXT_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(CONTEXT_PROPERTY_LIST *list, DWORD id)
{
CONTEXT_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(CONTEXT_PROPERTY_LIST *list, DWORD id)
{
DWORD ret;
EnterCriticalSection(&list->cs);
if (id)
{
CONTEXT_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(CONTEXT_PROPERTY_LIST *to, CONTEXT_PROPERTY_LIST *from)
{
CONTEXT_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);
}