blob: 89a6d2dc47d2c7ea9318dcf3a61778c8538c7f6c [file] [log] [blame]
/*
* Web Services on Devices
*
* Copyright 2017 Owen Rudge for CodeWeavers
*
* 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 <stdarg.h>
#define COBJMACROS
#include "windef.h"
#include "winbase.h"
#include "wine/debug.h"
#include "wine/list.h"
#include "wsdapi.h"
WINE_DEFAULT_DEBUG_CHANNEL(wsdapi);
#define MEMORY_ALLOCATION_MAGIC 0xB10C5EED
#define ALIGNMENT (2 * sizeof(void*))
#define ROUND_TO_ALIGNMENT(size) (((size) + ALIGNMENT - 1) & ~(ALIGNMENT - 1))
#define MEMORY_ALLOCATION_SIZE ROUND_TO_ALIGNMENT(sizeof(struct memory_allocation))
struct memory_allocation
{
int magic;
struct list entry;
struct list children;
};
static struct memory_allocation *find_allocation(void *ptr)
{
struct memory_allocation *allocation;
if (ptr == NULL)
{
return NULL;
}
allocation = (struct memory_allocation *)((char *)ptr - MEMORY_ALLOCATION_SIZE);
if (allocation->magic != MEMORY_ALLOCATION_MAGIC)
{
return NULL;
}
return allocation;
}
static void free_allocation(struct memory_allocation *item)
{
struct memory_allocation *child, *cursor;
LIST_FOR_EACH_ENTRY_SAFE(child, cursor, &item->children, struct memory_allocation, entry)
{
free_allocation(child);
}
list_remove(&item->entry);
item->magic = 0;
HeapFree(GetProcessHeap(), 0, item);
}
void * WINAPI WSDAllocateLinkedMemory(void *pParent, SIZE_T cbSize)
{
struct memory_allocation *allocation, *parent;
void *ptr;
TRACE("(%p, %lu)\n", pParent, cbSize);
ptr = HeapAlloc(GetProcessHeap(), 0, MEMORY_ALLOCATION_SIZE + cbSize);
if (ptr == NULL)
{
return NULL;
}
allocation = ptr;
allocation->magic = MEMORY_ALLOCATION_MAGIC;
list_init(&allocation->children);
/* See if we have a parent */
parent = find_allocation(pParent);
if (parent != NULL)
{
list_add_tail(&parent->children, &allocation->entry);
}
else
{
list_init(&allocation->entry);
}
return (char *)ptr + MEMORY_ALLOCATION_SIZE;
}
void WINAPI WSDAttachLinkedMemory(void *pParent, void *pChild)
{
struct memory_allocation *parent, *child;
TRACE("(%p, %p)\n", pParent, pChild);
child = find_allocation(pChild);
parent = find_allocation(pParent);
TRACE("child: %p, parent: %p\n", child, parent);
if ((child == NULL) || (parent == NULL))
{
return;
}
list_remove(&child->entry);
list_add_tail(&parent->children, &child->entry);
}
void WINAPI WSDDetachLinkedMemory(void *pVoid)
{
struct memory_allocation *allocation;
TRACE("(%p)\n", pVoid);
allocation = find_allocation(pVoid);
if (allocation == NULL)
{
TRACE("Memory allocation not found\n");
return;
}
list_remove(&allocation->entry);
}
void WINAPI WSDFreeLinkedMemory(void *pVoid)
{
struct memory_allocation *allocation;
TRACE("(%p)\n", pVoid);
allocation = find_allocation(pVoid);
if (allocation == NULL)
{
TRACE("Memory allocation not found\n");
return;
}
free_allocation(allocation);
}