Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/opcservices/package.c | 10 ++++++++++ dlls/opcservices/tests/opcservices.c | 9 ++++++--- 2 files changed, 16 insertions(+), 3 deletions(-)
diff --git a/dlls/opcservices/package.c b/dlls/opcservices/package.c index 074f3c8f99..e526ebff67 100644 --- a/dlls/opcservices/package.c +++ b/dlls/opcservices/package.c @@ -1301,13 +1301,23 @@ static HRESULT WINAPI opc_relationship_set_CreateRelationship(IOpcRelationshipSe const WCHAR *type, IUri *target_uri, OPC_URI_TARGET_MODE target_mode, IOpcRelationship **relationship) { struct opc_relationship_set *relationship_set = impl_from_IOpcRelationshipSet(iface); + DWORD length;
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);
+ if (!relationship) + return E_POINTER; + + *relationship = NULL; + if (!type || !target_uri) return E_POINTER;
+ if (IUri_GetPropertyLength(target_uri, Uri_PROPERTY_SCHEME_NAME, &length, 0) == S_OK && length != 0 + && target_mode == OPC_URI_TARGET_MODE_INTERNAL) + return OPC_E_INVALID_RELATIONSHIP_TARGET; + return opc_relationship_create(relationship_set, id, type, target_uri, target_mode, relationship); }
diff --git a/dlls/opcservices/tests/opcservices.c b/dlls/opcservices/tests/opcservices.c index 764dca1cf3..c5c8ee2599 100644 --- a/dlls/opcservices/tests/opcservices.c +++ b/dlls/opcservices/tests/opcservices.c @@ -362,21 +362,24 @@ static void test_relationship(void) hr = IOpcPackage_GetRelationshipSet(package, &rels); ok(SUCCEEDED(hr), "Failed to get part set, hr %#x.\n", hr);
+ rel = (void *)0xdeadbeef; hr = IOpcRelationshipSet_CreateRelationship(rels, NULL, NULL, NULL, OPC_URI_TARGET_MODE_INTERNAL, &rel); ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr); + ok(rel == NULL, "Unexpected instance %p.\n", rel);
+ rel = (void *)0xdeadbeef; hr = IOpcRelationshipSet_CreateRelationship(rels, NULL, typeW, NULL, OPC_URI_TARGET_MODE_INTERNAL, &rel); ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr); + ok(rel == NULL, "Unexpected instance %p.\n", rel);
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 */ + rel = (void *)0xdeadbeef; 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); - if (hr == S_OK) - IOpcRelationship_Release(rel); + ok(rel == NULL, "Unexpected instance %p.\n", rel);
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);
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/opcservices/package.c | 44 +++++++++++++++++----------- dlls/opcservices/tests/opcservices.c | 12 ++++++-- include/opcbase.idl | 1 + 3 files changed, 37 insertions(+), 20 deletions(-)
diff --git a/dlls/opcservices/package.c b/dlls/opcservices/package.c index e526ebff67..22bf793a77 100644 --- a/dlls/opcservices/package.c +++ b/dlls/opcservices/package.c @@ -1160,6 +1160,20 @@ static const IOpcRelationshipVtbl opc_relationship_vtbl = opc_relationship_GetTargetMode, };
+static struct opc_relationship *opc_relationshipset_get_rel(struct opc_relationship_set *relationship_set, + const WCHAR *id) +{ + size_t i; + + for (i = 0; i < relationship_set->count; i++) + { + if (!strcmpW(id, relationship_set->relationships[i]->id)) + return relationship_set->relationships[i]; + } + + return NULL; +} + 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) { @@ -1179,7 +1193,6 @@ static HRESULT opc_relationship_create(struct opc_relationship_set *set, const W relationship->source_uri = set->source_uri; IOpcUri_AddRef(relationship->source_uri);
- /* FIXME: test that id is unique */ if (id) relationship->id = opc_strdupW(id); else @@ -1190,8 +1203,16 @@ static HRESULT opc_relationship_create(struct opc_relationship_set *set, const W static const WCHAR fmtW[] = {'R','%','0','8','X',0}; DWORD generated;
+ /* FIXME: test that generated id is unique */ RtlGenRandom(&generated, sizeof(generated)); sprintfW(relationship->id, fmtW, generated); + + if (opc_relationshipset_get_rel(set, relationship->id)) + { + WARN("Newly generated id %s already exists.\n", debugstr_w(relationship->id)); + IOpcRelationship_Release(&relationship->IOpcRelationship_iface); + return E_FAIL; + } } }
@@ -1258,20 +1279,6 @@ static ULONG WINAPI opc_relationship_set_Release(IOpcRelationshipSet *iface) return refcount; }
-static struct opc_relationship *opc_relationshipset_get_item(struct opc_relationship_set *relationship_set, - const WCHAR *id) -{ - size_t i; - - for (i = 0; i < relationship_set->count; i++) - { - if (!strcmpW(id, relationship_set->relationships[i]->id)) - return relationship_set->relationships[i]; - } - - return NULL; -} - static HRESULT WINAPI opc_relationship_set_GetRelationship(IOpcRelationshipSet *iface, const WCHAR *id, IOpcRelationship **relationship) { @@ -1288,7 +1295,7 @@ static HRESULT WINAPI opc_relationship_set_GetRelationship(IOpcRelationshipSet * if (!id) return E_POINTER;
- if ((ret = opc_relationshipset_get_item(relationship_set, id))) + if ((ret = opc_relationshipset_get_rel(relationship_set, id))) { *relationship = &ret->IOpcRelationship_iface; IOpcRelationship_AddRef(*relationship); @@ -1314,6 +1321,9 @@ static HRESULT WINAPI opc_relationship_set_CreateRelationship(IOpcRelationshipSe if (!type || !target_uri) return E_POINTER;
+ if (id && opc_relationshipset_get_rel(relationship_set, id)) + return OPC_E_DUPLICATE_RELATIONSHIP; + if (IUri_GetPropertyLength(target_uri, Uri_PROPERTY_SCHEME_NAME, &length, 0) == S_OK && length != 0 && target_mode == OPC_URI_TARGET_MODE_INTERNAL) return OPC_E_INVALID_RELATIONSHIP_TARGET; @@ -1337,7 +1347,7 @@ static HRESULT WINAPI opc_relationship_set_RelationshipExists(IOpcRelationshipSe if (!id || !exists) return E_POINTER;
- *exists = opc_relationshipset_get_item(relationship_set, id) != NULL; + *exists = opc_relationshipset_get_rel(relationship_set, id) != NULL;
return S_OK; } diff --git a/dlls/opcservices/tests/opcservices.c b/dlls/opcservices/tests/opcservices.c index c5c8ee2599..2ef5677174 100644 --- a/dlls/opcservices/tests/opcservices.c +++ b/dlls/opcservices/tests/opcservices.c @@ -384,14 +384,20 @@ static void test_relationship(void) 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);
- hr = IOpcRelationshipSet_CreateRelationship(rels, NULL, typeW, target_uri, OPC_URI_TARGET_MODE_INTERNAL, &rel2); - 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));
+ hr = IOpcRelationshipSet_CreateRelationship(rels, id, typeW, target_uri, OPC_URI_TARGET_MODE_INTERNAL, &rel2); + ok(hr == OPC_E_DUPLICATE_RELATIONSHIP, "Failed to create relationship, hr %#x.\n", hr); + + hr = IOpcRelationshipSet_CreateRelationship(rels, id, typeW, target_uri2, OPC_URI_TARGET_MODE_INTERNAL, &rel2); + ok(hr == OPC_E_DUPLICATE_RELATIONSHIP, "Failed to create relationship, hr %#x.\n", hr); + + hr = IOpcRelationshipSet_CreateRelationship(rels, NULL, typeW, target_uri, OPC_URI_TARGET_MODE_INTERNAL, &rel2); + ok(SUCCEEDED(hr), "Failed to create relationship, hr %#x.\n", hr); + ret = 123; hr = IOpcRelationshipSet_RelationshipExists(rels, NULL, &ret); ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr); diff --git a/include/opcbase.idl b/include/opcbase.idl index d850753563..3df2df8063 100644 --- a/include/opcbase.idl +++ b/include/opcbase.idl @@ -45,6 +45,7 @@ cpp_quote("#define OPC_E_NONCONFORMING_URI MAKE_HRESULT(SEVERITY_ERROR, FACILITY cpp_quote("#define OPC_E_RELATIONSHIP_URI_REQUIRED MAKE_HRESULT(SEVERITY_ERROR, FACILITY_OPC, 0x3)") cpp_quote("#define OPC_E_DUPLICATE_PART MAKE_HRESULT(SEVERITY_ERROR, FACILITY_OPC, 0xb)") cpp_quote("#define OPC_E_INVALID_RELATIONSHIP_TARGET MAKE_HRESULT(SEVERITY_ERROR, FACILITY_OPC, 0x12)") +cpp_quote("#define OPC_E_DUPLICATE_RELATIONSHIP MAKE_HRESULT(SEVERITY_ERROR, FACILITY_OPC, 0x13)") cpp_quote("#define OPC_E_NO_SUCH_PART MAKE_HRESULT(SEVERITY_ERROR, FACILITY_OPC, 0x18)") cpp_quote("#define OPC_E_NO_SUCH_RELATIONSHIP MAKE_HRESULT(SEVERITY_ERROR, FACILITY_OPC, 0x48)") cpp_quote("#define OPC_E_ENUM_COLLECTION_CHANGED MAKE_HRESULT(SEVERITY_ERROR, FACILITY_OPC, 0x50)")
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/opcservices/compress.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/dlls/opcservices/compress.c b/dlls/opcservices/compress.c index 0f4555bdff..cf49f17aaa 100644 --- a/dlls/opcservices/compress.c +++ b/dlls/opcservices/compress.c @@ -134,6 +134,7 @@ HRESULT compress_create_archive(IStream *output, struct zip_archive **out)
archive->output = output; IStream_AddRef(archive->output); + archive->position = 0;
GetSystemTimeAsFileTime(&ft); FileTimeToDosDateTime(&ft, &date, &time);
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/opcservices/package.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/dlls/opcservices/package.c b/dlls/opcservices/package.c index 22bf793a77..d7467a5ef8 100644 --- a/dlls/opcservices/package.c +++ b/dlls/opcservices/package.c @@ -1888,7 +1888,10 @@ static HRESULT opc_package_write_rels(struct zip_archive *archive, IOpcRelations if (SUCCEEDED(hr)) hr = IOpcPartUri_GetRawUri(rels_uri, &rels_part_uri); if (SUCCEEDED(hr)) - hr = compress_add_file(archive, rels_part_uri, content, OPC_COMPRESSION_NORMAL); + { + /* Relationship part names always start with root '/', skip it. */ + hr = compress_add_file(archive, rels_part_uri + 1, content, OPC_COMPRESSION_NORMAL); + }
SysFreeString(rels_part_uri); IStream_Release(content);