Signed-off-by: Jactry Zeng jzeng@codeweavers.com --- dlls/comsvcs/comsvcs_private.h | 2 + dlls/comsvcs/property.c | 200 ++++++++++++++++++++++++++++++++- dlls/comsvcs/tests/property.c | 76 +++++++++++++ 3 files changed, 276 insertions(+), 2 deletions(-)
diff --git a/dlls/comsvcs/comsvcs_private.h b/dlls/comsvcs/comsvcs_private.h index eee6e9938c..3eeb9d751a 100644 --- a/dlls/comsvcs/comsvcs_private.h +++ b/dlls/comsvcs/comsvcs_private.h @@ -38,6 +38,7 @@ enum tid_t NULL_tid, ISharedPropertyGroupManager_tid, ISharedPropertyGroup_tid, + ISharedProperty_tid, LAST_tid };
@@ -46,6 +47,7 @@ static REFIID tid_ids[] = &IID_NULL, &IID_ISharedPropertyGroupManager, &IID_ISharedPropertyGroup, + &IID_ISharedProperty, };
HRESULT get_typeinfo(enum tid_t tid, ITypeInfo **typeinfo); diff --git a/dlls/comsvcs/property.c b/dlls/comsvcs/property.c index 83bacc7b49..e7b9fd8628 100644 --- a/dlls/comsvcs/property.c +++ b/dlls/comsvcs/property.c @@ -20,10 +20,19 @@
WINE_DEFAULT_DEBUG_CHANNEL(comsvcs);
+struct shared_property +{ + ISharedProperty ISharedProperty_iface; + LONG refcount; + BSTR name; +}; + struct property_group { ISharedPropertyGroup ISharedPropertyGroup_iface; ISharedPropertyGroupManager *parent; + struct shared_property *properties; + size_t capacity, count; LONG isolation, release; LONG refcount; BSTR name; @@ -50,6 +59,11 @@ static inline struct property_group *impl_from_ISharedPropertyGroup(ISharedPrope return CONTAINING_RECORD(iface, struct property_group, ISharedPropertyGroup_iface); }
+static inline struct shared_property *impl_from_ISharedProperty(ISharedProperty *iface) +{ + return CONTAINING_RECORD(iface, struct shared_property, ISharedProperty_iface); +} + static inline BOOL comsvcs_array_reserve(void **elements, size_t *capacity, size_t count, size_t size) { size_t new_capacity, max_capacity; @@ -81,6 +95,136 @@ static inline BOOL comsvcs_array_reserve(void **elements, size_t *capacity, size return TRUE; }
+static HRESULT WINAPI shared_property_QueryInterface(ISharedProperty *iface, REFIID riid, void **out) +{ + struct shared_property *property = impl_from_ISharedProperty(iface); + + TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out); + + *out = NULL; + if (IsEqualGUID(riid, &IID_IUnknown) + || IsEqualGUID(riid, &IID_IDispatch) + || IsEqualGUID(riid, &IID_ISharedProperty)) + { + *out = &property->ISharedProperty_iface; + IUnknown_AddRef((IUnknown*)*out); + + return S_OK; + } + + WARN("%s not implemented.\n", debugstr_guid(riid)); + return E_NOINTERFACE; +} + +static ULONG WINAPI shared_property_AddRef(ISharedProperty *iface) +{ + struct shared_property *property = impl_from_ISharedProperty(iface); + ULONG refcount = InterlockedIncrement(&property->refcount); + + TRACE("%p increasing refcount to %u.\n", iface, refcount); + + return refcount; +} + +static ULONG WINAPI shared_property_Release(ISharedProperty *iface) +{ + struct shared_property *property = impl_from_ISharedProperty(iface); + ULONG refcount = InterlockedDecrement(&property->refcount); + + TRACE("%p decreasing refcount to %u.\n", iface, refcount); + + if (!refcount) + { + SysFreeString(property->name); + } + + return refcount; +} + +static HRESULT WINAPI shared_property_GetTypeInfoCount(ISharedProperty *iface, UINT *info) +{ + TRACE("iface %p, info %p.\n", iface, info); + + if (!info) + return E_INVALIDARG; + *info = 1; + return S_OK; +} + +static HRESULT WINAPI shared_property_GetTypeInfo(ISharedProperty *iface, UINT index, LCID lcid, ITypeInfo **info) +{ + HRESULT hr; + + TRACE("iface %p, index %u, lcid %u, info %p.\n", iface, index, lcid, info); + + if (index) + return DISP_E_BADINDEX; + + hr = get_typeinfo(ISharedProperty_tid, info); + if (SUCCEEDED(hr)) + ITypeInfo_AddRef(*info); + return hr; +} + +static HRESULT WINAPI shared_property_GetIDsOfNames(ISharedProperty *iface, REFIID riid, LPOLESTR *names, UINT count, + LCID lcid, DISPID *dispid) +{ + ITypeInfo *typeinfo; + HRESULT hr; + + TRACE("iface %p, riid %s, names %p, count %u, lcid %u, dispid %p.\n", + iface, debugstr_guid(riid), names, count, lcid, dispid); + + hr = get_typeinfo(ISharedProperty_tid, &typeinfo); + if (SUCCEEDED(hr)) + { + hr = ITypeInfo_GetIDsOfNames(typeinfo, names, count, dispid); + ITypeInfo_Release(typeinfo); + } + + return hr; +} + +static HRESULT WINAPI shared_property_Invoke(ISharedProperty *iface, DISPID member, REFIID riid, LCID lcid, + WORD flags, DISPPARAMS *params, VARIANT *result, EXCEPINFO *except, UINT *argerr) +{ + ITypeInfo *typeinfo; + HRESULT hr; + + TRACE("iface %p, member %u, riid %s, lcid %u, flags %x, params %p, result %p, except %p, argerr %p.\n", + iface, member, debugstr_guid(riid), lcid, flags, params, result, except, argerr); + + hr = get_typeinfo(ISharedProperty_tid, &typeinfo); + if (SUCCEEDED(hr)) + hr = ITypeInfo_Invoke(typeinfo, iface, member, flags, params, result, except, argerr); + return hr; +} + +static HRESULT WINAPI shared_property_get_Value(ISharedProperty *iface, VARIANT *value) +{ + FIXME("iface %p, value %p: stub.\n", iface, value); + return E_NOTIMPL; +} + +static HRESULT WINAPI shared_property_put_Value(ISharedProperty *iface, VARIANT value) +{ + FIXME("iface %p, value %s: stub.\n", iface, debugstr_variant(&value)); + return E_NOTIMPL; +} + +static const ISharedPropertyVtbl shared_property_vtbl = +{ + shared_property_QueryInterface, + shared_property_AddRef, + shared_property_Release, + shared_property_GetTypeInfoCount, + shared_property_GetTypeInfo, + shared_property_GetIDsOfNames, + shared_property_Invoke, + shared_property_get_Value, + shared_property_put_Value +}; + static HRESULT WINAPI property_group_QueryInterface(ISharedPropertyGroup *iface, REFIID riid, void **out) { struct property_group *group = impl_from_ISharedPropertyGroup(iface); @@ -211,11 +355,53 @@ static HRESULT WINAPI property_group_get_PropertyByPosition(ISharedPropertyGroup return E_NOTIMPL; }
+ +static struct shared_property *find_shared_property(struct property_group *group, BSTR name) +{ + int index; + + for (index = 0; index < group->count; index++) + { + if (!lstrcmpW(group->properties[index].name, name)) + return &group->properties[index]; + } + return NULL; +} + static HRESULT WINAPI property_group_CreateProperty(ISharedPropertyGroup *iface, BSTR name, VARIANT_BOOL *exists, ISharedProperty **property) { - FIXME("iface %p, name %s, exists %p, property %p: stub.\n", iface, debugstr_w(name), exists, property); - return E_NOTIMPL; + struct property_group *group = impl_from_ISharedPropertyGroup(iface); + struct shared_property *shared_property; + HRESULT hr; + + TRACE("iface %p, name %s, exists %p, property %p.\n", iface, debugstr_w(name), exists, property); + + shared_property = find_shared_property(group, name); + if (!shared_property) + { + if (!comsvcs_array_reserve((void **)&group->properties, &group->capacity, group->count + 1, + sizeof(*group->properties))) + return E_OUTOFMEMORY; + + shared_property = &group->properties[group->count]; + shared_property->refcount = 1; + shared_property->name = SysAllocString(name); + shared_property->ISharedProperty_iface.lpVtbl = &shared_property_vtbl; + + group->count++; + *exists = FALSE; + *property = &shared_property->ISharedProperty_iface; + hr = S_OK; + } + else + { + *exists = TRUE; + hr = ISharedProperty_QueryInterface(&shared_property->ISharedProperty_iface, + &IID_ISharedProperty, (void **)property); + } + + return hr; }
static HRESULT WINAPI property_group_get_Property(ISharedPropertyGroup *iface, BSTR name, ISharedProperty **property) @@ -385,6 +571,16 @@ static HRESULT WINAPI group_manager_CreatePropertyGroup(ISharedPropertyGroupMana return E_OUTOFMEMORY;
property_group = &manager->property_groups[manager->count]; + + property_group->capacity = 0; + property_group->count = 0; + if (!comsvcs_array_reserve((void **)&property_group->properties, &property_group->capacity, 2, + sizeof(*property_group->properties))) + { + heap_free(manager->property_groups); + return E_OUTOFMEMORY; + } + property_group->ISharedPropertyGroup_iface.lpVtbl = &property_group_vtbl; property_group->parent = iface; property_group->isolation = *isolation; diff --git a/dlls/comsvcs/tests/property.c b/dlls/comsvcs/tests/property.c index fa83a49b94..971e1f4aed 100644 --- a/dlls/comsvcs/tests/property.c +++ b/dlls/comsvcs/tests/property.c @@ -308,12 +308,88 @@ static void test_property_group(void) ISharedPropertyGroupManager_Release(manager); }
+static void test_shared_property(void) +{ + ISharedProperty *property, *property1; + ISharedPropertyGroupManager *manager; + ULONG refcount, expected_refcount; + ISharedPropertyGroup *group; + BSTR name, property_name; + LONG isolation, release; + VARIANT_BOOL exists; + IDispatch *dispatch; + HRESULT hr; + struct test_name_id test_name_ids[] = + { + {L"Value", 0x0}, + }; + + hr = CoCreateInstance(&CLSID_SharedPropertyGroupManager, NULL, CLSCTX_INPROC_SERVER, + &IID_ISharedPropertyGroupManager, (void **)&manager); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + name = SysAllocString(L"testgroupname"); + isolation = 0; + release = 0; + exists = FALSE; + hr = ISharedPropertyGroupManager_CreatePropertyGroup(manager, name, &isolation, &release, &exists, &group); + ok(hr == S_OK, "Got hr %#x.\n", hr); + SysFreeString(name); + + property_name = SysAllocString(L"testpropertyname"); + exists = TRUE; + expected_refcount = get_refcount(group); + hr = ISharedPropertyGroup_CreateProperty(group, property_name, &exists, &property); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(!exists, "Got unexpected value: %d.\n", exists); + refcount = get_refcount(group); + ok(refcount == expected_refcount, "Got refcount: %d, expected %d.\n", refcount, expected_refcount); + + hr = ISharedPropertyGroup_get_PropertyByPosition(group, 0, &property1); + todo_wine ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr); + hr = ISharedPropertyGroup_get_PropertyByPosition(group, 1, &property1); + todo_wine ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr); + + exists = FALSE; + expected_refcount = get_refcount(property) + 1; + hr = ISharedPropertyGroup_CreateProperty(group, property_name, &exists, &property1); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(!!exists, "Got unexpected value: %d.\n", exists); + refcount = get_refcount(property); + ok(refcount == expected_refcount, "Got refcount: %d, expected %d.\n", refcount, expected_refcount); + expected_refcount--; + ISharedProperty_Release(property1); + refcount = get_refcount(property); + ok(refcount == expected_refcount, "Got refcount: %d, expected %d.\n", refcount, expected_refcount); + + expected_refcount = get_refcount(property) + 1; + property1 = NULL; + hr = ISharedPropertyGroup_get_Property(group, property_name, &property1); + todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr); + todo_wine ok(property1 == property, "Got wrong pointer %p.\n", property); + refcount = get_refcount(property); + todo_wine ok(refcount == expected_refcount, "Got refcount: %d, expected %d.\n", refcount, expected_refcount); + if (property1) + ISharedProperty_Release(property1); + SysFreeString(property_name); + + hr = ISharedProperty_QueryInterface(property, &IID_IDispatch, (void **)&dispatch); + ok(hr == S_OK, "Got hr %#x.\n", hr); + TEST_TYPEINFO(dispatch, test_name_ids, ARRAY_SIZE(test_name_ids), &IID_ISharedProperty); + IDispatch_Release(dispatch); + + ISharedProperty_Release(property); + ISharedPropertyGroup_Release(group); + ISharedPropertyGroupManager_Release(manager); +} + START_TEST(property) { CoInitialize(NULL);
test_interfaces(); test_property_group(); + test_shared_property();
CoUninitialize(); }