From 8fd70ff2bf06f4bc23b75747c6ccde09ebda8db5 Mon Sep 17 00:00:00 2001 From: Nikolay Sivov Date: Wed, 5 Sep 2018 08:37:23 +0300 Subject: [PATCH] opcservices: Keep parts in a set. Signed-off-by: Nikolay Sivov Signed-off-by: Alexandre Julliard --- dlls/opcservices/opc_private.h | 26 ++++++++++++++++++++++++++ dlls/opcservices/package.c | 23 +++++++++++++++++++++-- 2 files changed, 47 insertions(+), 2 deletions(-) diff --git a/dlls/opcservices/opc_private.h b/dlls/opcservices/opc_private.h index 4784b6c458f..30bcb0090c4 100644 --- a/dlls/opcservices/opc_private.h +++ b/dlls/opcservices/opc_private.h @@ -19,5 +19,31 @@ #include "msopc.h" #include "wine/heap.h" +static inline BOOL opc_array_reserve(void **elements, size_t *capacity, size_t count, size_t size) +{ + size_t new_capacity, max_capacity; + void *new_elements; + + if (count <= *capacity) + return TRUE; + + max_capacity = ~(SIZE_T)0 / size; + if (count > max_capacity) + return FALSE; + + new_capacity = max(4, *capacity); + while (new_capacity < count && new_capacity <= max_capacity / 2) + new_capacity *= 2; + if (new_capacity < count) + new_capacity = max_capacity; + + if (!(new_elements = heap_realloc(*elements, new_capacity * size))) + return FALSE; + + *elements = new_elements; + *capacity = new_capacity; + return TRUE; +} + extern HRESULT opc_package_create(IOpcPackage **package) DECLSPEC_HIDDEN; extern HRESULT opc_part_uri_create(const WCHAR *uri, IOpcPartUri **part_uri) DECLSPEC_HIDDEN; diff --git a/dlls/opcservices/package.c b/dlls/opcservices/package.c index cd4741d2202..869fb036e27 100644 --- a/dlls/opcservices/package.c +++ b/dlls/opcservices/package.c @@ -53,6 +53,10 @@ struct opc_part_set { IOpcPartSet IOpcPartSet_iface; LONG refcount; + + struct opc_part **parts; + size_t size; + size_t count; }; struct opc_relationship @@ -220,7 +224,7 @@ static const IOpcPartVtbl opc_part_vtbl = opc_part_GetCompressionOptions, }; -static HRESULT opc_part_create(IOpcPartUri *name, const WCHAR *content_type, +static HRESULT opc_part_create(struct opc_part_set *set, IOpcPartUri *name, const WCHAR *content_type, DWORD compression_options, IOpcPart **out) { struct opc_part *part; @@ -228,6 +232,9 @@ static HRESULT opc_part_create(IOpcPartUri *name, const WCHAR *content_type, if (!name) return E_POINTER; + if (!opc_array_reserve((void **)&set->parts, &set->size, set->count + 1, sizeof(*set->parts))) + return E_OUTOFMEMORY; + if (!(part = heap_alloc_zero(sizeof(*part)))) return E_OUTOFMEMORY; @@ -242,6 +249,9 @@ static HRESULT opc_part_create(IOpcPartUri *name, const WCHAR *content_type, return E_OUTOFMEMORY; } + set->parts[set->count++] = part; + IOpcPart_AddRef(&part->IOpcPart_iface); + *out = &part->IOpcPart_iface; TRACE("Created part %p.\n", *out); return S_OK; @@ -281,7 +291,14 @@ static ULONG WINAPI opc_part_set_Release(IOpcPartSet *iface) TRACE("%p decreasing refcount to %u.\n", iface, refcount); if (!refcount) + { + size_t i; + + for (i = 0; i < part_set->count; ++i) + IOpcPart_Release(&part_set->parts[i]->IOpcPart_iface); + heap_free(part_set->parts); heap_free(part_set); + } return refcount; } @@ -296,10 +313,12 @@ static HRESULT WINAPI opc_part_set_GetPart(IOpcPartSet *iface, IOpcPartUri *name static HRESULT WINAPI opc_part_set_CreatePart(IOpcPartSet *iface, IOpcPartUri *name, LPCWSTR content_type, OPC_COMPRESSION_OPTIONS compression_options, IOpcPart **part) { + struct opc_part_set *part_set = impl_from_IOpcPartSet(iface); + TRACE("iface %p, name %p, content_type %s, compression_options %#x, part %p.\n", iface, name, debugstr_w(content_type), compression_options, part); - return opc_part_create(name, content_type, compression_options, part); + return opc_part_create(part_set, name, content_type, compression_options, part); } static HRESULT WINAPI opc_part_set_DeletePart(IOpcPartSet *iface, IOpcPartUri *name)