| /* | |
| * 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); | |
| } |