opcservices: Implement IOpcRelationshipEnumerator.
Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
bacc74158e
commit
b11b9d5a25
|
@ -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);
|
||||
|
||||
|
|
Loading…
Reference in New Issue