Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- 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 4784b6c458..30bcb0090c 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 cd4741d220..869fb036e2 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)
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/opcservices/package.c | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-)
diff --git a/dlls/opcservices/package.c b/dlls/opcservices/package.c index 869fb036e2..e6716853eb 100644 --- a/dlls/opcservices/package.c +++ b/dlls/opcservices/package.c @@ -69,6 +69,10 @@ struct opc_relationship_set { IOpcRelationshipSet IOpcRelationshipSet_iface; LONG refcount; + + struct opc_relationship **relationships; + size_t size; + size_t count; };
static inline struct opc_package *impl_from_IOpcPackage(IOpcPackage *iface) @@ -440,16 +444,22 @@ static const IOpcRelationshipVtbl opc_relationship_vtbl = opc_relationship_GetTargetMode, };
-static HRESULT opc_relationship_create(IOpcRelationship **out) +static HRESULT opc_relationship_create(struct opc_relationship_set *set, IOpcRelationship **out) { struct opc_relationship *relationship;
+ if (!opc_array_reserve((void **)&set->relationships, &set->size, set->count + 1, sizeof(*set->relationships))) + return E_OUTOFMEMORY; + if (!(relationship = heap_alloc_zero(sizeof(*relationship)))) return E_OUTOFMEMORY;
relationship->IOpcRelationship_iface.lpVtbl = &opc_relationship_vtbl; relationship->refcount = 1;
+ set->relationships[set->count++] = relationship; + IOpcRelationship_AddRef(&relationship->IOpcRelationship_iface); + *out = &relationship->IOpcRelationship_iface; TRACE("Created relationship %p.\n", *out); return S_OK; @@ -489,7 +499,14 @@ static ULONG WINAPI opc_relationship_set_Release(IOpcRelationshipSet *iface) TRACE("%p decreasing refcount to %u.\n", iface, refcount);
if (!refcount) + { + size_t i; + + for (i = 0; i < relationship_set->count; ++i) + IOpcRelationship_Release(&relationship_set->relationships[i]->IOpcRelationship_iface); + heap_free(relationship_set->relationships); heap_free(relationship_set); + }
return refcount; } @@ -505,10 +522,12 @@ static HRESULT WINAPI opc_relationship_set_GetRelationship(IOpcRelationshipSet * static HRESULT WINAPI opc_relationship_set_CreateRelationship(IOpcRelationshipSet *iface, const WCHAR *id, const WCHAR *type, IUri *target_uri, OPC_URI_TARGET_MODE target_mode, IOpcRelationship **relationship) { + struct opc_relationship_set *relationship_set = impl_from_IOpcRelationshipSet(iface); + FIXME("iface %p, id %s, type %s, target_uri %p, target_mode %d, relationship %p stub!\n", iface, debugstr_w(id), debugstr_w(type), target_uri, target_mode, relationship);
- return opc_relationship_create(relationship); + return opc_relationship_create(relationship_set, relationship); }
static HRESULT WINAPI opc_relationship_set_DeleteRelationship(IOpcRelationshipSet *iface, const WCHAR *id)
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/opcservices/Makefile.in | 2 +- dlls/opcservices/package.c | 44 ++++++++++++++++--- dlls/opcservices/tests/Makefile.in | 2 +- dlls/opcservices/tests/opcservices.c | 64 ++++++++++++++++++++++++++++ include/opcbase.idl | 2 + include/winerror.h | 1 + 6 files changed, 108 insertions(+), 7 deletions(-)
diff --git a/dlls/opcservices/Makefile.in b/dlls/opcservices/Makefile.in index 47fbbe4cca..3e9907f011 100644 --- a/dlls/opcservices/Makefile.in +++ b/dlls/opcservices/Makefile.in @@ -1,5 +1,5 @@ MODULE = opcservices.dll -IMPORTS = uuid ole32 +IMPORTS = uuid ole32 advapi32
C_SRCS = \ factory.c \ diff --git a/dlls/opcservices/package.c b/dlls/opcservices/package.c index e6716853eb..1970fc447e 100644 --- a/dlls/opcservices/package.c +++ b/dlls/opcservices/package.c @@ -21,6 +21,7 @@ #include <stdarg.h> #include "windef.h" #include "winbase.h" +#include "ntsecapi.h"
#include "wine/debug.h" #include "wine/unicode.h" @@ -63,6 +64,8 @@ struct opc_relationship { IOpcRelationship IOpcRelationship_iface; LONG refcount; + + WCHAR *id; };
struct opc_relationship_set @@ -392,16 +395,22 @@ static ULONG WINAPI opc_relationship_Release(IOpcRelationship *iface) TRACE("%p decreasing refcount to %u.\n", iface, refcount);
if (!refcount) + { + CoTaskMemFree(relationship->id); heap_free(relationship); + }
return refcount; }
static HRESULT WINAPI opc_relationship_GetId(IOpcRelationship *iface, WCHAR **id) { - FIXME("iface %p, id %p stub!\n", iface, id); + struct opc_relationship *relationship = impl_from_IOpcRelationship(iface);
- return E_NOTIMPL; + TRACE("iface %p, id %p.\n", iface, id); + + *id = opc_strdupW(relationship->id); + return *id ? S_OK : E_OUTOFMEMORY; }
static HRESULT WINAPI opc_relationship_GetRelationshipType(IOpcRelationship *iface, WCHAR **type) @@ -444,7 +453,7 @@ static const IOpcRelationshipVtbl opc_relationship_vtbl = opc_relationship_GetTargetMode, };
-static HRESULT opc_relationship_create(struct opc_relationship_set *set, IOpcRelationship **out) +static HRESULT opc_relationship_create(struct opc_relationship_set *set, const WCHAR *id, IOpcRelationship **out) { struct opc_relationship *relationship;
@@ -457,6 +466,28 @@ static HRESULT opc_relationship_create(struct opc_relationship_set *set, IOpcRel relationship->IOpcRelationship_iface.lpVtbl = &opc_relationship_vtbl; relationship->refcount = 1;
+ /* FIXME: test that id is unique */ + if (id) + relationship->id = opc_strdupW(id); + else + { + relationship->id = CoTaskMemAlloc(10 * sizeof(WCHAR)); + if (relationship->id) + { + static const WCHAR fmtW[] = {'R','%','0','8','X',0}; + DWORD generated; + + RtlGenRandom(&generated, sizeof(generated)); + sprintfW(relationship->id, fmtW, generated); + } + } + + if (!relationship->id) + { + heap_free(relationship); + return E_OUTOFMEMORY; + } + set->relationships[set->count++] = relationship; IOpcRelationship_AddRef(&relationship->IOpcRelationship_iface);
@@ -524,10 +555,13 @@ static HRESULT WINAPI opc_relationship_set_CreateRelationship(IOpcRelationshipSe { struct opc_relationship_set *relationship_set = impl_from_IOpcRelationshipSet(iface);
- FIXME("iface %p, id %s, type %s, target_uri %p, target_mode %d, relationship %p stub!\n", iface, debugstr_w(id), + TRACE("iface %p, id %s, type %s, target_uri %p, target_mode %d, relationship %p.\n", iface, debugstr_w(id), debugstr_w(type), target_uri, target_mode, relationship);
- return opc_relationship_create(relationship_set, relationship); + if (!type || !target_uri) + return E_POINTER; + + return opc_relationship_create(relationship_set, id, relationship); }
static HRESULT WINAPI opc_relationship_set_DeleteRelationship(IOpcRelationshipSet *iface, const WCHAR *id) diff --git a/dlls/opcservices/tests/Makefile.in b/dlls/opcservices/tests/Makefile.in index 7c0963cc60..202bf87d68 100644 --- a/dlls/opcservices/tests/Makefile.in +++ b/dlls/opcservices/tests/Makefile.in @@ -1,5 +1,5 @@ TESTDLL = opcservices.dll -IMPORTS = ole32 +IMPORTS = ole32 urlmon
C_SRCS = \ opcservices.c diff --git a/dlls/opcservices/tests/opcservices.c b/dlls/opcservices/tests/opcservices.c index 5dc0d8c772..8232a7ed83 100644 --- a/dlls/opcservices/tests/opcservices.c +++ b/dlls/opcservices/tests/opcservices.c @@ -24,6 +24,7 @@ #include "windows.h" #include "initguid.h" #include "msopc.h" +#include "urlmon.h"
#include "wine/test.h"
@@ -204,6 +205,68 @@ static void test_file_stream(void) DeleteFileW(pathW); }
+static void test_relationship_id(void) +{ + static const WCHAR absoluteW[] = {'f','i','l','e',':','/','/','h','o','s','t','/','f','i','l','e','.','t','x','t',0}; + static const WCHAR targetW[] = {'t','a','r','g','e','t',0}; + static const WCHAR typeW[] = {'t','y','p','e',0}; + IUri *target_uri, *target_uri2; + IOpcRelationshipSet *rels; + IOpcRelationship *rel; + IOpcFactory *factory; + IOpcPackage *package; + HRESULT hr; + WCHAR *id; + + factory = create_factory(); + + hr = IOpcFactory_CreatePackage(factory, &package); + ok(SUCCEEDED(hr) || broken(hr == E_NOTIMPL) /* Vista */, "Failed to create a package, hr %#x.\n", hr); + if (FAILED(hr)) + return; + + hr = CreateUri(targetW, Uri_CREATE_ALLOW_RELATIVE, 0, &target_uri); + ok(SUCCEEDED(hr), "Failed to create target uri, hr %#x.\n", hr); + + hr = CreateUri(absoluteW, 0, 0, &target_uri2); + ok(SUCCEEDED(hr), "Failed to create target uri, hr %#x.\n", hr); + + hr = IOpcPackage_GetRelationshipSet(package, &rels); + ok(SUCCEEDED(hr), "Failed to get part set, hr %#x.\n", hr); + + hr = IOpcRelationshipSet_CreateRelationship(rels, NULL, NULL, NULL, OPC_URI_TARGET_MODE_INTERNAL, &rel); + ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr); + + hr = IOpcRelationshipSet_CreateRelationship(rels, NULL, typeW, NULL, OPC_URI_TARGET_MODE_INTERNAL, &rel); + ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr); + + hr = IOpcRelationshipSet_CreateRelationship(rels, NULL, NULL, target_uri, OPC_URI_TARGET_MODE_INTERNAL, &rel); + ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr); + + /* Absolute target uri with internal mode */ + hr = IOpcRelationshipSet_CreateRelationship(rels, NULL, typeW, target_uri2, OPC_URI_TARGET_MODE_INTERNAL, &rel); +todo_wine + ok(hr == OPC_E_INVALID_RELATIONSHIP_TARGET, "Unexpected hr %#x.\n", hr); + + hr = IOpcRelationshipSet_CreateRelationship(rels, NULL, typeW, target_uri, OPC_URI_TARGET_MODE_INTERNAL, &rel); + ok(SUCCEEDED(hr), "Failed to create relationship, hr %#x.\n", hr); + + /* Autogenerated relationship id */ + hr = IOpcRelationship_GetId(rel, &id); + ok(SUCCEEDED(hr), "Failed to get id, hr %#x.\n", hr); + ok(lstrlenW(id) == 9 && *id == 'R', "Unexpected relationship id %s.\n", wine_dbgstr_w(id)); + CoTaskMemFree(id); + + IOpcRelationship_Release(rel); + + IOpcRelationshipSet_Release(rels); + + IUri_Release(target_uri); + IUri_Release(target_uri2); + IOpcPackage_Release(package); + IOpcFactory_Release(factory); +} + START_TEST(opcservices) { IOpcFactory *factory; @@ -220,6 +283,7 @@ START_TEST(opcservices)
test_package(); test_file_stream(); + test_relationship_id();
IOpcFactory_Release(factory);
diff --git a/include/opcbase.idl b/include/opcbase.idl index 33f56ac077..80f459fe8b 100644 --- a/include/opcbase.idl +++ b/include/opcbase.idl @@ -40,3 +40,5 @@ typedef [v1_enum] enum OPC_URI_TARGET_MODE_INTERNAL = 0, OPC_URI_TARGET_MODE_EXTERNAL = 1, } OPC_URI_TARGET_MODE; + +cpp_quote("#define OPC_E_INVALID_RELATIONSHIP_TARGET MAKE_HRESULT(SEVERITY_ERROR, FACILITY_OPC, 0x12)") diff --git a/include/winerror.h b/include/winerror.h index 6193c24087..d78c91e84e 100644 --- a/include/winerror.h +++ b/include/winerror.h @@ -59,6 +59,7 @@ #define FACILITY_PLA 48 #define FACILITY_FVE 49 #define FACILITY_WINDOWS_DEFENDER 80 +#define FACILITY_OPC 81 #define FACILITY_DIRECT3D11 0x87c #define FACILITY_AUDCLNT 0x889
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/opcservices/package.c | 28 ++++++++++++++++++++++------ dlls/opcservices/tests/opcservices.c | 16 +++++++++++++--- 2 files changed, 35 insertions(+), 9 deletions(-)
diff --git a/dlls/opcservices/package.c b/dlls/opcservices/package.c index 1970fc447e..235dc974a0 100644 --- a/dlls/opcservices/package.c +++ b/dlls/opcservices/package.c @@ -66,6 +66,8 @@ struct opc_relationship LONG refcount;
WCHAR *id; + IUri *target; + OPC_URI_TARGET_MODE target_mode; };
struct opc_relationship_set @@ -397,6 +399,7 @@ static ULONG WINAPI opc_relationship_Release(IOpcRelationship *iface) if (!refcount) { CoTaskMemFree(relationship->id); + IUri_Release(relationship->target); heap_free(relationship); }
@@ -429,16 +432,25 @@ static HRESULT WINAPI opc_relationship_GetSourceUri(IOpcRelationship *iface, IOp
static HRESULT WINAPI opc_relationship_GetTargetUri(IOpcRelationship *iface, IUri **target) { - FIXME("iface %p, target %p stub!\n", iface, target); + struct opc_relationship *relationship = impl_from_IOpcRelationship(iface);
- return E_NOTIMPL; + TRACE("iface %p, target %p.\n", iface, target); + + *target = relationship->target; + IUri_AddRef(*target); + + return S_OK; }
static HRESULT WINAPI opc_relationship_GetTargetMode(IOpcRelationship *iface, OPC_URI_TARGET_MODE *target_mode) { - FIXME("iface %p, target_mode %p stub!\n", iface, target_mode); + struct opc_relationship *relationship = impl_from_IOpcRelationship(iface);
- return E_NOTIMPL; + TRACE("iface %p, target_mode %p.\n", iface, target_mode); + + *target_mode = relationship->target_mode; + + return S_OK; }
static const IOpcRelationshipVtbl opc_relationship_vtbl = @@ -453,7 +465,8 @@ static const IOpcRelationshipVtbl opc_relationship_vtbl = opc_relationship_GetTargetMode, };
-static HRESULT opc_relationship_create(struct opc_relationship_set *set, const WCHAR *id, IOpcRelationship **out) +static HRESULT opc_relationship_create(struct opc_relationship_set *set, const WCHAR *id, IUri *target_uri, + OPC_URI_TARGET_MODE target_mode, IOpcRelationship **out) { struct opc_relationship *relationship;
@@ -488,6 +501,9 @@ static HRESULT opc_relationship_create(struct opc_relationship_set *set, const W return E_OUTOFMEMORY; }
+ relationship->target = target_uri; + IUri_AddRef(relationship->target); + set->relationships[set->count++] = relationship; IOpcRelationship_AddRef(&relationship->IOpcRelationship_iface);
@@ -561,7 +577,7 @@ static HRESULT WINAPI opc_relationship_set_CreateRelationship(IOpcRelationshipSe if (!type || !target_uri) return E_POINTER;
- return opc_relationship_create(relationship_set, id, relationship); + return opc_relationship_create(relationship_set, id, target_uri, target_mode, relationship); }
static HRESULT WINAPI opc_relationship_set_DeleteRelationship(IOpcRelationshipSet *iface, const WCHAR *id) diff --git a/dlls/opcservices/tests/opcservices.c b/dlls/opcservices/tests/opcservices.c index 8232a7ed83..28507162c7 100644 --- a/dlls/opcservices/tests/opcservices.c +++ b/dlls/opcservices/tests/opcservices.c @@ -205,16 +205,17 @@ static void test_file_stream(void) DeleteFileW(pathW); }
-static void test_relationship_id(void) +static void test_relationship(void) { static const WCHAR absoluteW[] = {'f','i','l','e',':','/','/','h','o','s','t','/','f','i','l','e','.','t','x','t',0}; static const WCHAR targetW[] = {'t','a','r','g','e','t',0}; static const WCHAR typeW[] = {'t','y','p','e',0}; - IUri *target_uri, *target_uri2; + IUri *target_uri, *target_uri2, *uri; IOpcRelationshipSet *rels; IOpcRelationship *rel; IOpcFactory *factory; IOpcPackage *package; + DWORD mode; HRESULT hr; WCHAR *id;
@@ -257,6 +258,15 @@ todo_wine ok(lstrlenW(id) == 9 && *id == 'R', "Unexpected relationship id %s.\n", wine_dbgstr_w(id)); CoTaskMemFree(id);
+ hr = IOpcRelationship_GetTargetUri(rel, &uri); + ok(SUCCEEDED(hr), "Failed to get target uri, hr %#x.\n", hr); + ok(uri == target_uri, "Unexpected uri.\n"); + IUri_Release(uri); + + hr = IOpcRelationship_GetTargetMode(rel, &mode); + ok(SUCCEEDED(hr), "Failed to get target mode, hr %#x.\n", hr); + ok(mode == OPC_URI_TARGET_MODE_INTERNAL, "Unexpected mode %d.\n", mode); + IOpcRelationship_Release(rel);
IOpcRelationshipSet_Release(rels); @@ -283,7 +293,7 @@ START_TEST(opcservices)
test_package(); test_file_stream(); - test_relationship_id(); + test_relationship();
IOpcFactory_Release(factory);
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/opcservices/package.c | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-)
diff --git a/dlls/opcservices/package.c b/dlls/opcservices/package.c index 235dc974a0..cac89c523e 100644 --- a/dlls/opcservices/package.c +++ b/dlls/opcservices/package.c @@ -66,6 +66,7 @@ struct opc_relationship LONG refcount;
WCHAR *id; + WCHAR *type; IUri *target; OPC_URI_TARGET_MODE target_mode; }; @@ -399,6 +400,7 @@ static ULONG WINAPI opc_relationship_Release(IOpcRelationship *iface) if (!refcount) { CoTaskMemFree(relationship->id); + CoTaskMemFree(relationship->type); IUri_Release(relationship->target); heap_free(relationship); } @@ -418,9 +420,12 @@ static HRESULT WINAPI opc_relationship_GetId(IOpcRelationship *iface, WCHAR **id
static HRESULT WINAPI opc_relationship_GetRelationshipType(IOpcRelationship *iface, WCHAR **type) { - FIXME("iface %p, type %p stub!\n", iface, type); + struct opc_relationship *relationship = impl_from_IOpcRelationship(iface);
- return E_NOTIMPL; + TRACE("iface %p, type %p.\n", iface, type); + + *type = opc_strdupW(relationship->type); + return *type ? S_OK : E_OUTOFMEMORY; }
static HRESULT WINAPI opc_relationship_GetSourceUri(IOpcRelationship *iface, IOpcUri **uri) @@ -465,8 +470,8 @@ static const IOpcRelationshipVtbl opc_relationship_vtbl = opc_relationship_GetTargetMode, };
-static HRESULT opc_relationship_create(struct opc_relationship_set *set, const WCHAR *id, IUri *target_uri, - OPC_URI_TARGET_MODE target_mode, IOpcRelationship **out) +static HRESULT opc_relationship_create(struct opc_relationship_set *set, const WCHAR *id, const WCHAR *type, + IUri *target_uri, OPC_URI_TARGET_MODE target_mode, IOpcRelationship **out) { struct opc_relationship *relationship;
@@ -479,6 +484,9 @@ static HRESULT opc_relationship_create(struct opc_relationship_set *set, const W relationship->IOpcRelationship_iface.lpVtbl = &opc_relationship_vtbl; relationship->refcount = 1;
+ relationship->target = target_uri; + IUri_AddRef(relationship->target); + /* FIXME: test that id is unique */ if (id) relationship->id = opc_strdupW(id); @@ -495,15 +503,13 @@ static HRESULT opc_relationship_create(struct opc_relationship_set *set, const W } }
- if (!relationship->id) + relationship->type = opc_strdupW(type); + if (!relationship->id || !relationship->type) { - heap_free(relationship); + IOpcRelationship_Release(&relationship->IOpcRelationship_iface); return E_OUTOFMEMORY; }
- relationship->target = target_uri; - IUri_AddRef(relationship->target); - set->relationships[set->count++] = relationship; IOpcRelationship_AddRef(&relationship->IOpcRelationship_iface);
@@ -577,7 +583,7 @@ static HRESULT WINAPI opc_relationship_set_CreateRelationship(IOpcRelationshipSe if (!type || !target_uri) return E_POINTER;
- return opc_relationship_create(relationship_set, id, target_uri, target_mode, relationship); + return opc_relationship_create(relationship_set, id, type, target_uri, target_mode, relationship); }
static HRESULT WINAPI opc_relationship_set_DeleteRelationship(IOpcRelationshipSet *iface, const WCHAR *id)
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/opcservices/factory.c | 6 ++++-- dlls/opcservices/opc_private.h | 1 + dlls/opcservices/tests/Makefile.in | 2 +- dlls/opcservices/tests/opcservices.c | 21 +++++++++++++++++++++ dlls/opcservices/uri.c | 23 ++++++++++++++++++++++- 5 files changed, 49 insertions(+), 4 deletions(-)
diff --git a/dlls/opcservices/factory.c b/dlls/opcservices/factory.c index 7d72b39b7b..0c16cc2501 100644 --- a/dlls/opcservices/factory.c +++ b/dlls/opcservices/factory.c @@ -309,9 +309,11 @@ static ULONG WINAPI opc_factory_Release(IOpcFactory *iface)
static HRESULT WINAPI opc_factory_CreatePackageRootUri(IOpcFactory *iface, IOpcUri **uri) { - FIXME("iface %p, uri %p stub!\n", iface, uri); + static const WCHAR rootW[] = {'/',0};
- return E_NOTIMPL; + TRACE("iface %p, uri %p.\n", iface, uri); + + return opc_uri_create(rootW, uri); }
static HRESULT WINAPI opc_factory_CreatePartUri(IOpcFactory *iface, LPCWSTR uri, IOpcPartUri **part_uri) diff --git a/dlls/opcservices/opc_private.h b/dlls/opcservices/opc_private.h index 30bcb0090c..80b1e954b7 100644 --- a/dlls/opcservices/opc_private.h +++ b/dlls/opcservices/opc_private.h @@ -47,3 +47,4 @@ static inline BOOL opc_array_reserve(void **elements, size_t *capacity, size_t c
extern HRESULT opc_package_create(IOpcPackage **package) DECLSPEC_HIDDEN; extern HRESULT opc_part_uri_create(const WCHAR *uri, IOpcPartUri **part_uri) DECLSPEC_HIDDEN; +extern HRESULT opc_uri_create(const WCHAR *uri, IOpcUri **opc_uri) DECLSPEC_HIDDEN; diff --git a/dlls/opcservices/tests/Makefile.in b/dlls/opcservices/tests/Makefile.in index 202bf87d68..4fa222e927 100644 --- a/dlls/opcservices/tests/Makefile.in +++ b/dlls/opcservices/tests/Makefile.in @@ -1,5 +1,5 @@ TESTDLL = opcservices.dll -IMPORTS = ole32 urlmon +IMPORTS = ole32 urlmon oleaut32
C_SRCS = \ opcservices.c diff --git a/dlls/opcservices/tests/opcservices.c b/dlls/opcservices/tests/opcservices.c index 28507162c7..9af7aa49b9 100644 --- a/dlls/opcservices/tests/opcservices.c +++ b/dlls/opcservices/tests/opcservices.c @@ -210,14 +210,18 @@ static void test_relationship(void) static const WCHAR absoluteW[] = {'f','i','l','e',':','/','/','h','o','s','t','/','f','i','l','e','.','t','x','t',0}; static const WCHAR targetW[] = {'t','a','r','g','e','t',0}; static const WCHAR typeW[] = {'t','y','p','e',0}; + static const WCHAR rootW[] = {'/',0}; IUri *target_uri, *target_uri2, *uri; IOpcRelationshipSet *rels; IOpcRelationship *rel; IOpcFactory *factory; IOpcPackage *package; + IOpcUri *source_uri; + IUnknown *unk; DWORD mode; HRESULT hr; WCHAR *id; + BSTR str;
factory = create_factory();
@@ -267,6 +271,23 @@ todo_wine ok(SUCCEEDED(hr), "Failed to get target mode, hr %#x.\n", hr); ok(mode == OPC_URI_TARGET_MODE_INTERNAL, "Unexpected mode %d.\n", mode);
+ /* Source uri */ + hr = IOpcRelationship_GetSourceUri(rel, &source_uri); +todo_wine + ok(SUCCEEDED(hr), "Failed to get source uri, hr %#x.\n", hr); + + hr = IOpcUri_QueryInterface(source_uri, &IID_IOpcPartUri, (void **)&unk); + ok(hr == E_NOINTERFACE, "Unexpected hr %#x.\n", hr); + + str = NULL; + hr = IOpcUri_GetRawUri(source_uri, &str); + ok(SUCCEEDED(hr), "Failed to get raw uri, hr %#x.\n", hr); +todo_wine + ok(!lstrcmpW(rootW, str), "Unexpected uri %s.\n", wine_dbgstr_w(str)); + SysFreeString(str); + + IOpcUri_Release(source_uri); + IOpcRelationship_Release(rel);
IOpcRelationshipSet_Release(rels); diff --git a/dlls/opcservices/uri.c b/dlls/opcservices/uri.c index 60881e865e..651c2e38f0 100644 --- a/dlls/opcservices/uri.c +++ b/dlls/opcservices/uri.c @@ -32,6 +32,7 @@ struct opc_uri { IOpcPartUri IOpcPartUri_iface; LONG refcount; + BOOL is_part_uri; };
static inline struct opc_uri *impl_from_IOpcPartUri(IOpcPartUri *iface) @@ -41,9 +42,13 @@ static inline struct opc_uri *impl_from_IOpcPartUri(IOpcPartUri *iface)
static HRESULT WINAPI opc_uri_QueryInterface(IOpcPartUri *iface, REFIID iid, void **out) { + struct opc_uri *uri = impl_from_IOpcPartUri(iface); + TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
- if (IsEqualIID(iid, &IID_IOpcPartUri) || + if ((uri->is_part_uri && IsEqualIID(iid, &IID_IOpcPartUri)) || + IsEqualIID(iid, &IID_IOpcUri) || + IsEqualIID(iid, &IID_IUri) || IsEqualIID(iid, &IID_IUnknown)) { *out = iface; @@ -348,8 +353,24 @@ HRESULT opc_part_uri_create(const WCHAR *str, IOpcPartUri **out)
uri->IOpcPartUri_iface.lpVtbl = &opc_part_uri_vtbl; uri->refcount = 1; + uri->is_part_uri = TRUE;
*out = &uri->IOpcPartUri_iface; TRACE("Created part uri %p.\n", *out); return S_OK; } + +HRESULT opc_uri_create(const WCHAR *str, IOpcUri **out) +{ + struct opc_uri *uri; + + if (!(uri = heap_alloc_zero(sizeof(*uri)))) + return E_OUTOFMEMORY; + + uri->IOpcPartUri_iface.lpVtbl = &opc_part_uri_vtbl; + uri->refcount = 1; + + *out = (IOpcUri *)&uri->IOpcPartUri_iface; + TRACE("Created part uri %p.\n", *out); + return S_OK; +}
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/opcservices/Makefile.in | 2 +- dlls/opcservices/uri.c | 190 ++++++++++++++++++++++++----------- 2 files changed, 135 insertions(+), 57 deletions(-)
diff --git a/dlls/opcservices/Makefile.in b/dlls/opcservices/Makefile.in index 3e9907f011..f165b5ceb8 100644 --- a/dlls/opcservices/Makefile.in +++ b/dlls/opcservices/Makefile.in @@ -1,5 +1,5 @@ MODULE = opcservices.dll -IMPORTS = uuid ole32 advapi32 +IMPORTS = uuid ole32 advapi32 urlmon
C_SRCS = \ factory.c \ diff --git a/dlls/opcservices/uri.c b/dlls/opcservices/uri.c index 651c2e38f0..594abc36f1 100644 --- a/dlls/opcservices/uri.c +++ b/dlls/opcservices/uri.c @@ -33,6 +33,8 @@ struct opc_uri IOpcPartUri IOpcPartUri_iface; LONG refcount; BOOL is_part_uri; + + IUri *uri; };
static inline struct opc_uri *impl_from_IOpcPartUri(IOpcPartUri *iface) @@ -78,7 +80,10 @@ static ULONG WINAPI opc_uri_Release(IOpcPartUri *iface) TRACE("%p decreasing refcount to %u.\n", iface, refcount);
if (!refcount) + { + IUri_Release(uri->uri); heap_free(uri); + }
return refcount; } @@ -86,180 +91,230 @@ static ULONG WINAPI opc_uri_Release(IOpcPartUri *iface) static HRESULT WINAPI opc_uri_GetPropertyBSTR(IOpcPartUri *iface, Uri_PROPERTY property, BSTR *value, DWORD flags) { - FIXME("iface %p, property %d, value %p, flags %#x stub!\n", iface, property, value, flags); + struct opc_uri *uri = impl_from_IOpcPartUri(iface);
- return E_NOTIMPL; + TRACE("iface %p, property %d, value %p, flags %#x.\n", iface, property, value, flags); + + return IUri_GetPropertyBSTR(uri->uri, property, value, flags); }
static HRESULT WINAPI opc_uri_GetPropertyLength(IOpcPartUri *iface, Uri_PROPERTY property, DWORD *length, DWORD flags) { - FIXME("iface %p, property %d, length %p, flags %#x stub!\n", iface, property, length, flags); + struct opc_uri *uri = impl_from_IOpcPartUri(iface);
- return E_NOTIMPL; + TRACE("iface %p, property %d, length %p, flags %#x.\n", iface, property, length, flags); + + return IUri_GetPropertyLength(uri->uri, property, length, flags); }
static HRESULT WINAPI opc_uri_GetPropertyDWORD(IOpcPartUri *iface, Uri_PROPERTY property, DWORD *value, DWORD flags) { - FIXME("iface %p, property %d, value %p, flags %#x stub!\n", iface, property, value, flags); + struct opc_uri *uri = impl_from_IOpcPartUri(iface);
- return E_NOTIMPL; + TRACE("iface %p, property %d, value %p, flags %#x.\n", iface, property, value, flags); + + return IUri_GetPropertyDWORD(uri->uri, property, value, flags); }
static HRESULT WINAPI opc_uri_HasProperty(IOpcPartUri *iface, Uri_PROPERTY property, BOOL *has_property) { - FIXME("iface %p, property %d, has_property %p stub!\n", iface, property, has_property); + struct opc_uri *uri = impl_from_IOpcPartUri(iface);
- return E_NOTIMPL; + TRACE("iface %p, property %d, has_property %p.\n", iface, property, has_property); + + return IUri_HasProperty(uri->uri, property, has_property); }
static HRESULT WINAPI opc_uri_GetAbsoluteUri(IOpcPartUri *iface, BSTR *value) { - FIXME("iface %p, value %p stub!\n", iface, value); + struct opc_uri *uri = impl_from_IOpcPartUri(iface);
- return E_NOTIMPL; + TRACE("iface %p, value %p.\n", iface, value); + + return IUri_GetAbsoluteUri(uri->uri, value); }
static HRESULT WINAPI opc_uri_GetAuthority(IOpcPartUri *iface, BSTR *value) { - FIXME("iface %p, value %p stub!\n", iface, value); + struct opc_uri *uri = impl_from_IOpcPartUri(iface);
- return E_NOTIMPL; + TRACE("iface %p, value %p.\n", iface, value); + + return IUri_GetAuthority(uri->uri, value); }
static HRESULT WINAPI opc_uri_GetDisplayUri(IOpcPartUri *iface, BSTR *value) { - FIXME("iface %p, value %p stub!\n", iface, value); + struct opc_uri *uri = impl_from_IOpcPartUri(iface);
- return E_NOTIMPL; + TRACE("iface %p, value %p.\n", iface, value); + + return IUri_GetDisplayUri(uri->uri, value); }
static HRESULT WINAPI opc_uri_GetDomain(IOpcPartUri *iface, BSTR *value) { - FIXME("iface %p, value %p stub!\n", iface, value); + struct opc_uri *uri = impl_from_IOpcPartUri(iface);
- return E_NOTIMPL; + TRACE("iface %p, value %p.\n", iface, value); + + return IUri_GetDomain(uri->uri, value); }
static HRESULT WINAPI opc_uri_GetExtension(IOpcPartUri *iface, BSTR *value) { - FIXME("iface %p, value %p stub!\n", iface, value); + struct opc_uri *uri = impl_from_IOpcPartUri(iface);
- return E_NOTIMPL; + TRACE("iface %p, value %p.\n", iface, value); + + return IUri_GetExtension(uri->uri, value); }
static HRESULT WINAPI opc_uri_GetFragment(IOpcPartUri *iface, BSTR *value) { - FIXME("iface %p, value %p stub!\n", iface, value); + struct opc_uri *uri = impl_from_IOpcPartUri(iface);
- return E_NOTIMPL; + TRACE("iface %p, value %p.\n", iface, value); + + return IUri_GetFragment(uri->uri, value); }
static HRESULT WINAPI opc_uri_GetHost(IOpcPartUri *iface, BSTR *value) { - FIXME("iface %p, value %p stub!\n", iface, value); + struct opc_uri *uri = impl_from_IOpcPartUri(iface);
- return E_NOTIMPL; + TRACE("iface %p, value %p.\n", iface, value); + + return IUri_GetHost(uri->uri, value); }
static HRESULT WINAPI opc_uri_GetPassword(IOpcPartUri *iface, BSTR *value) { - FIXME("iface %p, value %p stub!\n", iface, value); + struct opc_uri *uri = impl_from_IOpcPartUri(iface);
- return E_NOTIMPL; + TRACE("iface %p, value %p.\n", iface, value); + + return IUri_GetPassword(uri->uri, value); }
static HRESULT WINAPI opc_uri_GetPath(IOpcPartUri *iface, BSTR *value) { - FIXME("iface %p, value %p stub!\n", iface, value); + struct opc_uri *uri = impl_from_IOpcPartUri(iface);
- return E_NOTIMPL; + TRACE("iface %p, value %p.\n", iface, value); + + return IUri_GetPath(uri->uri, value); }
static HRESULT WINAPI opc_uri_GetPathAndQuery(IOpcPartUri *iface, BSTR *value) { - FIXME("iface %p, value %p stub!\n", iface, value); + struct opc_uri *uri = impl_from_IOpcPartUri(iface);
- return E_NOTIMPL; + TRACE("iface %p, value %p.\n", iface, value); + + return IUri_GetPathAndQuery(uri->uri, value); }
static HRESULT WINAPI opc_uri_GetQuery(IOpcPartUri *iface, BSTR *value) { - FIXME("iface %p, value %p stub!\n", iface, value); + struct opc_uri *uri = impl_from_IOpcPartUri(iface);
- return E_NOTIMPL; + TRACE("iface %p, value %p.\n", iface, value); + + return IUri_GetQuery(uri->uri, value); }
static HRESULT WINAPI opc_uri_GetRawUri(IOpcPartUri *iface, BSTR *value) { - FIXME("iface %p, value %p stub!\n", iface, value); + struct opc_uri *uri = impl_from_IOpcPartUri(iface);
- return E_NOTIMPL; + TRACE("iface %p, value %p.\n", iface, value); + + return IUri_GetRawUri(uri->uri, value); }
static HRESULT WINAPI opc_uri_GetSchemeName(IOpcPartUri *iface, BSTR *value) { - FIXME("iface %p, value %p stub!\n", iface, value); + struct opc_uri *uri = impl_from_IOpcPartUri(iface);
- return E_NOTIMPL; + TRACE("iface %p, value %p.\n", iface, value); + + return IUri_GetSchemeName(uri->uri, value); }
static HRESULT WINAPI opc_uri_GetUserInfo(IOpcPartUri *iface, BSTR *value) { - FIXME("iface %p, value %p stub!\n", iface, value); + struct opc_uri *uri = impl_from_IOpcPartUri(iface);
- return E_NOTIMPL; + TRACE("iface %p, value %p.\n", iface, value); + + return IUri_GetUserInfo(uri->uri, value); }
static HRESULT WINAPI opc_uri_GetUserName(IOpcPartUri *iface, BSTR *value) { - FIXME("iface %p, value %p stub!\n", iface, value); + struct opc_uri *uri = impl_from_IOpcPartUri(iface);
- return E_NOTIMPL; + TRACE("iface %p, value %p.\n", iface, value); + + return IUri_GetUserName(uri->uri, value); }
static HRESULT WINAPI opc_uri_GetHostType(IOpcPartUri *iface, DWORD *value) { - FIXME("iface %p, value %p stub!\n", iface, value); + struct opc_uri *uri = impl_from_IOpcPartUri(iface);
- return E_NOTIMPL; + TRACE("iface %p, value %p.\n", iface, value); + + return IUri_GetHostType(uri->uri, value); }
static HRESULT WINAPI opc_uri_GetPort(IOpcPartUri *iface, DWORD *value) { - FIXME("iface %p, value %p stub!\n", iface, value); + struct opc_uri *uri = impl_from_IOpcPartUri(iface);
- return E_NOTIMPL; + TRACE("iface %p, value %p.\n", iface, value); + + return IUri_GetPort(uri->uri, value); }
static HRESULT WINAPI opc_uri_GetScheme(IOpcPartUri *iface, DWORD *value) { - FIXME("iface %p, value %p stub!\n", iface, value); + struct opc_uri *uri = impl_from_IOpcPartUri(iface);
- return E_NOTIMPL; + TRACE("iface %p, value %p.\n", iface, value); + + return IUri_GetScheme(uri->uri, value); }
static HRESULT WINAPI opc_uri_GetZone(IOpcPartUri *iface, DWORD *value) { - FIXME("iface %p, value %p stub!\n", iface, value); + struct opc_uri *uri = impl_from_IOpcPartUri(iface);
- return E_NOTIMPL; + TRACE("iface %p, value %p.\n", iface, value); + + return IUri_GetZone(uri->uri, value); }
static HRESULT WINAPI opc_uri_GetProperties(IOpcPartUri *iface, DWORD *flags) { - FIXME("iface %p, flags %p stub!\n", iface, flags); + struct opc_uri *uri = impl_from_IOpcPartUri(iface);
- return E_NOTIMPL; + TRACE("iface %p, flags %p.\n", iface, flags); + + return IUri_GetProperties(uri->uri, flags); }
-static HRESULT WINAPI opc_uri_IsEqual(IOpcPartUri *iface, IUri *uri, BOOL *is_equal) +static HRESULT WINAPI opc_uri_IsEqual(IOpcPartUri *iface, IUri *comparand, BOOL *is_equal) { - FIXME("iface %p, uri %p, is_equal %p stub!\n", iface, uri, is_equal); + struct opc_uri *uri = impl_from_IOpcPartUri(iface);
- return E_NOTIMPL; + TRACE("iface %p, comparand %p, is_equal %p.\n", iface, comparand, is_equal); + + return IUri_IsEqual(uri->uri, comparand, is_equal); }
static HRESULT WINAPI opc_uri_GetRelationshipsPartUri(IOpcPartUri *iface, IOpcPartUri **part_uri) @@ -344,16 +399,34 @@ static const IOpcPartUriVtbl opc_part_uri_vtbl = opc_uri_IsRelationshipsPartUri, };
+static HRESULT opc_part_uri_init(struct opc_uri *object, BOOL is_part_uri, const WCHAR *uri) +{ + HRESULT hr; + + object->IOpcPartUri_iface.lpVtbl = &opc_part_uri_vtbl; + object->refcount = 1; + object->is_part_uri = is_part_uri; + + if (FAILED(hr = CreateUri(uri, Uri_CREATE_ALLOW_RELATIVE, 0, &object->uri))) + return hr; + + return S_OK; +} + HRESULT opc_part_uri_create(const WCHAR *str, IOpcPartUri **out) { struct opc_uri *uri; + HRESULT hr;
if (!(uri = heap_alloc_zero(sizeof(*uri)))) return E_OUTOFMEMORY;
- uri->IOpcPartUri_iface.lpVtbl = &opc_part_uri_vtbl; - uri->refcount = 1; - uri->is_part_uri = TRUE; + if (FAILED(hr = opc_part_uri_init(uri, TRUE, str))) + { + WARN("Failed to init part uri, hr %#x.\n", hr); + heap_free(uri); + return hr; + }
*out = &uri->IOpcPartUri_iface; TRACE("Created part uri %p.\n", *out); @@ -363,12 +436,17 @@ HRESULT opc_part_uri_create(const WCHAR *str, IOpcPartUri **out) HRESULT opc_uri_create(const WCHAR *str, IOpcUri **out) { struct opc_uri *uri; + HRESULT hr;
if (!(uri = heap_alloc_zero(sizeof(*uri)))) return E_OUTOFMEMORY;
- uri->IOpcPartUri_iface.lpVtbl = &opc_part_uri_vtbl; - uri->refcount = 1; + if (FAILED(hr = opc_part_uri_init(uri, FALSE, str))) + { + WARN("Failed to init uri, hr %#x.\n", hr); + heap_free(uri); + return hr; + }
*out = (IOpcUri *)&uri->IOpcPartUri_iface; TRACE("Created part uri %p.\n", *out);