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