Commit b11b9d5a authored by Nikolay Sivov's avatar Nikolay Sivov Committed by Alexandre Julliard

opcservices: Implement IOpcRelationshipEnumerator.

parent bacc7415
......@@ -90,6 +90,16 @@ struct opc_part_set
GUID id;
};
struct opc_rel_enum
{
IOpcRelationshipEnumerator IOpcRelationshipEnumerator_iface;
LONG refcount;
struct opc_relationship_set *rel_set;
size_t pos;
GUID id;
};
struct opc_relationship
{
IOpcRelationship IOpcRelationship_iface;
......@@ -111,6 +121,7 @@ struct opc_relationship_set
size_t size;
size_t count;
IOpcUri *source_uri;
GUID id;
};
static inline struct opc_package *impl_from_IOpcPackage(IOpcPackage *iface)
......@@ -148,6 +159,11 @@ static inline struct opc_part_enum *impl_from_IOpcPartEnumerator(IOpcPartEnumera
return CONTAINING_RECORD(iface, struct opc_part_enum, IOpcPartEnumerator_iface);
}
static inline struct opc_rel_enum *impl_from_IOpcRelationshipEnumerator(IOpcRelationshipEnumerator *iface)
{
return CONTAINING_RECORD(iface, struct opc_rel_enum, IOpcRelationshipEnumerator_iface);
}
static void opc_content_release(struct opc_content *content)
{
ULONG refcount = InterlockedDecrement(&content->refcount);
......@@ -320,6 +336,167 @@ static HRESULT opc_part_enum_create(struct opc_part_set *part_set, IOpcPartEnume
return S_OK;
}
static HRESULT opc_rel_enum_create(struct opc_relationship_set *rel_set, IOpcRelationshipEnumerator **out);
static HRESULT WINAPI opc_rel_enum_QueryInterface(IOpcRelationshipEnumerator *iface, REFIID iid, void **out)
{
TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
if (IsEqualIID(&IID_IOpcRelationshipEnumerator, iid) ||
IsEqualIID(&IID_IUnknown, iid))
{
*out = iface;
IOpcRelationshipEnumerator_AddRef(iface);
return S_OK;
}
*out = NULL;
WARN("Unsupported interface %s.\n", debugstr_guid(iid));
return E_NOINTERFACE;
}
static ULONG WINAPI opc_rel_enum_AddRef(IOpcRelationshipEnumerator *iface)
{
struct opc_rel_enum *rel_enum = impl_from_IOpcRelationshipEnumerator(iface);
ULONG refcount = InterlockedIncrement(&rel_enum->refcount);
TRACE("%p increasing refcount to %u.\n", iface, refcount);
return refcount;
}
static ULONG WINAPI opc_rel_enum_Release(IOpcRelationshipEnumerator *iface)
{
struct opc_rel_enum *rel_enum = impl_from_IOpcRelationshipEnumerator(iface);
ULONG refcount = InterlockedDecrement(&rel_enum->refcount);
TRACE("%p decreasing refcount to %u.\n", iface, refcount);
if (!refcount)
{
IOpcRelationshipSet_Release(&rel_enum->rel_set->IOpcRelationshipSet_iface);
heap_free(rel_enum);
}
return refcount;
}
static BOOL has_rel_collection_changed(const struct opc_rel_enum *rel_enum)
{
return !IsEqualGUID(&rel_enum->id, &rel_enum->rel_set->id);
}
static HRESULT WINAPI opc_rel_enum_MoveNext(IOpcRelationshipEnumerator *iface, BOOL *has_next)
{
struct opc_rel_enum *rel_enum = impl_from_IOpcRelationshipEnumerator(iface);
TRACE("iface %p, has_next %p.\n", iface, has_next);
if (!has_next)
return E_POINTER;
if (has_rel_collection_changed(rel_enum))
return OPC_E_ENUM_COLLECTION_CHANGED;
if (rel_enum->rel_set->count && (rel_enum->pos == ~(size_t)0 || rel_enum->pos < rel_enum->rel_set->count))
rel_enum->pos++;
*has_next = rel_enum->pos < rel_enum->rel_set->count;
return S_OK;
}
static HRESULT WINAPI opc_rel_enum_MovePrevious(IOpcRelationshipEnumerator *iface, BOOL *has_previous)
{
struct opc_rel_enum *rel_enum = impl_from_IOpcRelationshipEnumerator(iface);
TRACE("iface %p, has_previous %p.\n", iface, has_previous);
if (!has_previous)
return E_POINTER;
if (has_rel_collection_changed(rel_enum))
return OPC_E_ENUM_COLLECTION_CHANGED;
if (rel_enum->pos != ~(size_t)0)
rel_enum->pos--;
*has_previous = rel_enum->pos != ~(size_t)0;
return S_OK;
}
static HRESULT WINAPI opc_rel_enum_GetCurrent(IOpcRelationshipEnumerator *iface, IOpcRelationship **rel)
{
struct opc_rel_enum *rel_enum = impl_from_IOpcRelationshipEnumerator(iface);
TRACE("iface %p, rel %p.\n", iface, rel);
if (!rel)
return E_POINTER;
*rel = NULL;
if (has_rel_collection_changed(rel_enum))
return OPC_E_ENUM_COLLECTION_CHANGED;
if (rel_enum->pos < rel_enum->rel_set->count)
{
*rel = &rel_enum->rel_set->relationships[rel_enum->pos]->IOpcRelationship_iface;
IOpcRelationship_AddRef(*rel);
}
return *rel ? S_OK : OPC_E_ENUM_INVALID_POSITION;
}
static HRESULT WINAPI opc_rel_enum_Clone(IOpcRelationshipEnumerator *iface, IOpcRelationshipEnumerator **out)
{
struct opc_rel_enum *rel_enum = impl_from_IOpcRelationshipEnumerator(iface);
TRACE("iface %p, out %p.\n", iface, out);
if (!out)
return E_POINTER;
if (has_rel_collection_changed(rel_enum))
{
*out = NULL;
return OPC_E_ENUM_COLLECTION_CHANGED;
}
return opc_rel_enum_create(rel_enum->rel_set, out);
}
static const IOpcRelationshipEnumeratorVtbl opc_rel_enum_vtbl =
{
opc_rel_enum_QueryInterface,
opc_rel_enum_AddRef,
opc_rel_enum_Release,
opc_rel_enum_MoveNext,
opc_rel_enum_MovePrevious,
opc_rel_enum_GetCurrent,
opc_rel_enum_Clone,
};
static HRESULT opc_rel_enum_create(struct opc_relationship_set *rel_set, IOpcRelationshipEnumerator **out)
{
struct opc_rel_enum *rel_enum;
if (!(rel_enum = heap_alloc_zero(sizeof(*rel_enum))))
return E_OUTOFMEMORY;
rel_enum->IOpcRelationshipEnumerator_iface.lpVtbl = &opc_rel_enum_vtbl;
rel_enum->refcount = 1;
rel_enum->rel_set = rel_set;
IOpcRelationshipSet_AddRef(&rel_set->IOpcRelationshipSet_iface);
rel_enum->pos = ~(size_t)0;
rel_enum->id = rel_set->id;
*out = &rel_enum->IOpcRelationshipEnumerator_iface;
TRACE("Created relationship enumerator %p.\n", *out);
return S_OK;
}
static HRESULT WINAPI opc_content_stream_QueryInterface(IStream *iface, REFIID iid, void **out)
{
TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
......@@ -978,6 +1155,7 @@ static HRESULT opc_relationship_create(struct opc_relationship_set *set, const W
set->relationships[set->count++] = relationship;
IOpcRelationship_AddRef(&relationship->IOpcRelationship_iface);
CoCreateGuid(&set->id);
*out = &relationship->IOpcRelationship_iface;
TRACE("Created relationship %p.\n", *out);
......@@ -1108,9 +1286,14 @@ static HRESULT WINAPI opc_relationship_set_RelationshipExists(IOpcRelationshipSe
static HRESULT WINAPI opc_relationship_set_GetEnumerator(IOpcRelationshipSet *iface,
IOpcRelationshipEnumerator **enumerator)
{
FIXME("iface %p, enumerator %p stub!\n", iface, enumerator);
struct opc_relationship_set *relationship_set = impl_from_IOpcRelationshipSet(iface);
return E_NOTIMPL;
TRACE("iface %p, enumerator %p.\n", iface, enumerator);
if (!enumerator)
return E_POINTER;
return opc_rel_enum_create(relationship_set, enumerator);
}
static HRESULT WINAPI opc_relationship_set_GetEnumeratorForType(IOpcRelationshipSet *iface, const WCHAR *type,
......
......@@ -753,6 +753,168 @@ static void test_part_enumerator(void)
IOpcFactory_Release(factory);
}
static void test_rels_enumerator(void)
{
static const WCHAR typeW[] = {'t','y','p','e','/','s','u','b','t','y','p','e',0};
static const WCHAR targetW[] = {'t','a','r','g','e','t',0};
IOpcRelationshipEnumerator *relsenum, *relsenum2;
IOpcRelationship *rel, *rel2;
IOpcPackage *package;
IOpcFactory *factory;
IOpcRelationshipSet *rels;
IUri *target_uri;
HRESULT hr;
BOOL ret;
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))
{
IOpcFactory_Release(factory);
return;
}
hr = IOpcPackage_GetRelationshipSet(package, &rels);
ok(SUCCEEDED(hr), "Failed to get part set, hr %#x.\n", hr);
hr = IOpcRelationshipSet_GetEnumerator(rels, NULL);
ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
hr = IOpcRelationshipSet_GetEnumerator(rels, &relsenum);
ok(SUCCEEDED(hr), "Failed to get enumerator, hr %#x.\n", hr);
hr = IOpcRelationshipSet_GetEnumerator(rels, &relsenum2);
ok(SUCCEEDED(hr), "Failed to get enumerator, hr %#x.\n", hr);
ok(relsenum != relsenum2, "Unexpected instance.\n");
IOpcRelationshipEnumerator_Release(relsenum2);
hr = IOpcRelationshipEnumerator_GetCurrent(relsenum, NULL);
ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
hr = IOpcRelationshipEnumerator_GetCurrent(relsenum, &rel);
ok(hr == OPC_E_ENUM_INVALID_POSITION, "Unexpected hr %#x.\n", hr);
hr = IOpcRelationshipEnumerator_MoveNext(relsenum, NULL);
ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
ret = TRUE;
hr = IOpcRelationshipEnumerator_MoveNext(relsenum, &ret);
ok(hr == S_OK, "Failed to move, hr %#x.\n", hr);
ok(!ret, "Unexpected result %d.\n", ret);
ret = TRUE;
hr = IOpcRelationshipEnumerator_MovePrevious(relsenum, &ret);
ok(hr == S_OK, "Failed to move, hr %#x.\n", hr);
ok(!ret, "Unexpected result %d.\n", ret);
hr = CreateUri(targetW, Uri_CREATE_ALLOW_RELATIVE, 0, &target_uri);
ok(SUCCEEDED(hr), "Failed to create target uri, 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);
IUri_Release(target_uri);
rel2 = (void *)0xdeadbeef;
hr = IOpcRelationshipEnumerator_GetCurrent(relsenum, &rel2);
ok(hr == OPC_E_ENUM_COLLECTION_CHANGED, "Unexpected hr %#x.\n", hr);
ok(rel2 == NULL, "Unexpected instance.\n");
hr = IOpcRelationshipEnumerator_MoveNext(relsenum, NULL);
ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
ret = 123;
hr = IOpcRelationshipEnumerator_MoveNext(relsenum, &ret);
ok(hr == OPC_E_ENUM_COLLECTION_CHANGED, "Unexpected hr %#x.\n", hr);
ok(ret == 123, "Unexpected result %d.\n", ret);
hr = IOpcRelationshipEnumerator_MovePrevious(relsenum, NULL);
ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
ret = 123;
hr = IOpcRelationshipEnumerator_MovePrevious(relsenum, &ret);
ok(hr == OPC_E_ENUM_COLLECTION_CHANGED, "Unexpected hr %#x.\n", hr);
ok(ret == 123, "Unexpected result %d.\n", ret);
hr = IOpcRelationshipEnumerator_Clone(relsenum, NULL);
ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
relsenum2 = (void *)0xdeadbeef;
hr = IOpcRelationshipEnumerator_Clone(relsenum, &relsenum2);
ok(hr == OPC_E_ENUM_COLLECTION_CHANGED, "Unexpected hr %#x.\n", hr);
ok(relsenum2 == NULL, "Unexpected instance.\n");
IOpcRelationshipEnumerator_Release(relsenum);
hr = IOpcRelationshipSet_GetEnumerator(rels, &relsenum);
ok(SUCCEEDED(hr), "Failed to get enumerator, hr %#x.\n", hr);
rel2 = (void *)0xdeadbeef;
hr = IOpcRelationshipEnumerator_GetCurrent(relsenum, &rel2);
ok(hr == OPC_E_ENUM_INVALID_POSITION, "Unexpected hr %#x.\n", hr);
ok(rel2 == NULL, "Unexpected instance.\n");
hr = IOpcRelationshipEnumerator_MoveNext(relsenum, &ret);
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
ok(ret, "Unexpected result %d.\n", ret);
hr = IOpcRelationshipEnumerator_GetCurrent(relsenum, &rel2);
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
ok(rel2 == rel, "Unexpected instance.\n");
IOpcRelationship_Release(rel2);
hr = IOpcRelationshipEnumerator_MoveNext(relsenum, &ret);
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
ok(!ret, "Unexpected result %d.\n", ret);
rel2 = (void *)0xdeadbeef;
hr = IOpcRelationshipEnumerator_GetCurrent(relsenum, &rel2);
ok(hr == OPC_E_ENUM_INVALID_POSITION, "Unexpected hr %#x.\n", hr);
ok(rel2 == NULL, "Unexpected instance.\n");
hr = IOpcRelationshipEnumerator_MovePrevious(relsenum, &ret);
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
ok(ret, "Unexpected result %d.\n", ret);
hr = IOpcRelationshipEnumerator_GetCurrent(relsenum, &rel2);
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
ok(rel2 == rel, "Unexpected instance.\n");
IOpcRelationship_Release(rel2);
hr = IOpcRelationshipEnumerator_MovePrevious(relsenum, &ret);
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
ok(!ret, "Unexpected result %d.\n", ret);
hr = IOpcRelationshipEnumerator_GetCurrent(relsenum, &rel2);
ok(hr == OPC_E_ENUM_INVALID_POSITION, "Unexpected hr %#x.\n", hr);
hr = IOpcRelationshipEnumerator_Clone(relsenum, &relsenum2);
ok(SUCCEEDED(hr), "Clone failed, hr %#x.\n", hr);
hr = IOpcRelationshipEnumerator_MoveNext(relsenum2, &ret);
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
ok(ret, "Unexpected result %d.\n", ret);
hr = IOpcRelationshipEnumerator_GetCurrent(relsenum2, &rel2);
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
IOpcRelationship_Release(rel2);
hr = IOpcRelationshipEnumerator_GetCurrent(relsenum, &rel2);
ok(hr == OPC_E_ENUM_INVALID_POSITION, "Unexpected hr %#x.\n", hr);
IOpcRelationshipEnumerator_Release(relsenum2);
IOpcRelationshipEnumerator_Release(relsenum);
IOpcRelationship_Release(rel);
IOpcRelationshipSet_Release(rels);
IOpcPackage_Release(package);
IOpcFactory_Release(factory);
}
START_TEST(opcservices)
{
IOpcFactory *factory;
......@@ -772,6 +934,7 @@ START_TEST(opcservices)
test_relationship();
test_rel_part_uri();
test_part_enumerator();
test_rels_enumerator();
IOpcFactory_Release(factory);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment