diff --git a/dlls/wsdapi/Makefile.in b/dlls/wsdapi/Makefile.in index 56912ee6ba4..7d63fe26d62 100644 --- a/dlls/wsdapi/Makefile.in +++ b/dlls/wsdapi/Makefile.in @@ -4,4 +4,5 @@ IMPORTS = kernel32 C_SRCS = \ discovery.c \ - main.c + main.c \ + memory.c diff --git a/dlls/wsdapi/memory.c b/dlls/wsdapi/memory.c new file mode 100644 index 00000000000..89a6d2dc47d --- /dev/null +++ b/dlls/wsdapi/memory.c @@ -0,0 +1,166 @@ +/* + * 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 + +#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); +} diff --git a/dlls/wsdapi/tests/Makefile.in b/dlls/wsdapi/tests/Makefile.in index c351d1043c4..2b20c6311e3 100644 --- a/dlls/wsdapi/tests/Makefile.in +++ b/dlls/wsdapi/tests/Makefile.in @@ -2,4 +2,5 @@ TESTDLL = wsdapi.dll IMPORTS = wsdapi ole32 user32 C_SRCS = \ - discovery.c + discovery.c \ + memory.c diff --git a/dlls/wsdapi/tests/memory.c b/dlls/wsdapi/tests/memory.c new file mode 100644 index 00000000000..9fb1a25476c --- /dev/null +++ b/dlls/wsdapi/tests/memory.c @@ -0,0 +1,74 @@ +/* + * Web Services on Devices + * Memory tests + * + * 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 + */ + +#define COBJMACROS + +#include + +#include "wine/test.h" +#include "wsdapi.h" + +#define ALIGNMENT (2 * sizeof(void*)) +#define NUM_ITERATIONS 100 + +static void AllocateLinkedMemory_tests(void) +{ + void *alloc1; + void *alloc2; + void *alloc_ptrs[NUM_ITERATIONS]; + int i; + + /* Test a parentless allocation */ + alloc1 = WSDAllocateLinkedMemory(NULL, 1024); + ok(alloc1 != NULL, "WSDAllocateLinkedMemory with null parent failed\n"); + + WSDFreeLinkedMemory(alloc1); + + /* Test a parented allocation */ + alloc1 = WSDAllocateLinkedMemory(NULL, 1024); + ok(alloc1 != NULL, "WSDAllocateLinkedMemory with null parent failed\n"); + + alloc2 = WSDAllocateLinkedMemory(alloc1, 1024); + ok(alloc2 != NULL, "WSDAllocateLinkedMemory with parent failed\n"); + + WSDFreeLinkedMemory(alloc1); + + /* Try allocating against the freed parent */ + alloc2 = WSDAllocateLinkedMemory(alloc1, 1024); + ok(alloc2 != NULL, "WSDAllocateLinkedMemory with parent failed\n"); + + /* Test that the returned pointers are aligned as expected */ + for (i = 0; i < NUM_ITERATIONS; i++) + { + alloc_ptrs[i] = WSDAllocateLinkedMemory(NULL, i); + ok(((UINT_PTR)alloc_ptrs[i] % ALIGNMENT) == 0, "WSDAllocateLinkedMemory returned pointer not aligned (size = %d).\n", i); + } + + for (i = 0; i < NUM_ITERATIONS; i++) + { + WSDFreeLinkedMemory(alloc_ptrs[i]); + } +} + +START_TEST(memory) +{ + AllocateLinkedMemory_tests(); +} diff --git a/dlls/wsdapi/wsdapi.spec b/dlls/wsdapi/wsdapi.spec index 3e1d2b69bad..7145f7d2cff 100644 --- a/dlls/wsdapi/wsdapi.spec +++ b/dlls/wsdapi/wsdapi.spec @@ -4,8 +4,8 @@ @ stub WSDNotifyNetworkChange @ stub WSDRemoveFirewallCheck @ stub WSDXMLCompareNames -@ stub WSDAllocateLinkedMemory -@ stub WSDAttachLinkedMemory +@ stdcall WSDAllocateLinkedMemory(ptr long) +@ stdcall WSDAttachLinkedMemory(ptr ptr) @ stub WSDCompareEndpoints @ stub WSDCopyEndpoint @ stub WSDCreateDeviceHost2 @@ -26,8 +26,8 @@ @ stub WSDCreateUdpAddress @ stub WSDCreateUdpMessageParameters @ stub WSDCreateUdpTransport -@ stub WSDDetachLinkedMemory -@ stub WSDFreeLinkedMemory +@ stdcall WSDDetachLinkedMemory(ptr) +@ stdcall WSDFreeLinkedMemory(ptr) @ stub WSDGenerateFault @ stub WSDGenerateFaultEx @ stub WSDGenerateRandomDelay diff --git a/include/Makefile.in b/include/Makefile.in index 6f5372815c3..497c76f4777 100644 --- a/include/Makefile.in +++ b/include/Makefile.in @@ -693,6 +693,7 @@ HEADER_SRCS = \ ws2tcpip.h \ wsdapi.h \ wsdtypes.h \ + wsdutil.h \ wsdxmldom.h \ wshisotp.h \ wsipx.h \ diff --git a/include/wsdapi.h b/include/wsdapi.h index dec095472b2..d71721e15b4 100644 --- a/include/wsdapi.h +++ b/include/wsdapi.h @@ -24,5 +24,6 @@ #include #include #include +#include #endif diff --git a/include/wsdutil.h b/include/wsdutil.h new file mode 100644 index 00000000000..8a89eb1da2f --- /dev/null +++ b/include/wsdutil.h @@ -0,0 +1,27 @@ +/* + * 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 + */ + +#ifndef WSDUTIL_H +#define WSDUTIL_H + +void * WINAPI WSDAllocateLinkedMemory(void *pParent, SIZE_T cbSize); +void WINAPI WSDAttachLinkedMemory(void *pParent, void *pChild); +void WINAPI WSDDetachLinkedMemory(void *pVoid); +void WINAPI WSDFreeLinkedMemory(void *pVoid); + +#endif