On 8/17/20 3:53 PM, Jactry Zeng wrote:
+HRESULT WINAPI group_manager_create(IClassFactory *iface, IUnknown *outer, REFIID riid, void **out) +{ + HRESULT hr; + + if (outer) + return CLASS_E_NOAGGREGATION; + + if (!group_manager) + { + group_manager = heap_alloc(sizeof(*group_manager)); + if (!group_manager) + { + out = NULL; + return E_OUTOFMEMORY; + } + + group_manager->ISharedPropertyGroupManager_iface.lpVtbl = &group_manager_vtbl; + group_manager->refcount = 1; + } + hr = ISharedPropertyGroupManager_QueryInterface(&group_manager->ISharedPropertyGroupManager_iface, riid, out); + + return hr; +} If the intent is to have single instance of this object, such initialization needs to be safe.
static void test_interfaces(void) +{ + ISharedPropertyGroupManager *manager, *manager1; + ULONG refcount, expected_refcount; + IDispatch *dispatch; + IUnknown *unk; + HRESULT hr; + + hr = CoCreateInstance(&CLSID_SharedPropertyGroupManager, &test_outer, CLSCTX_INPROC_SERVER, + &IID_ISharedPropertyGroupManager, (void **)&manager); + ok(hr == CLASS_E_NOAGGREGATION, "Got hr %#x.\n", hr); + + hr = CoCreateInstance(&CLSID_SharedPropertyGroupManager, NULL, CLSCTX_INPROC_SERVER, + &IID_ISharedPropertyGroupManager, (void **)&manager); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + expected_refcount = get_refcount(manager) + 1; + hr = CoCreateInstance(&CLSID_SharedPropertyGroupManager, NULL, CLSCTX_INPROC_SERVER, + &IID_ISharedPropertyGroupManager, (void **)&manager1); + ok(hr == S_OK, "Got hr %#x.\n", hr); + refcount = get_refcount(manager1); + ok(refcount == expected_refcount, "Got refcount: %d, expected %d.\n", refcount, expected_refcount); + refcount = get_refcount(manager); + ok(refcount == expected_refcount, "Got refcount: %d, expected %d.\n", refcount, expected_refcount); + ISharedPropertyGroupManager_Release(manager1); + + hr = CoCreateInstance(&CLSID_SharedPropertyGroupManager, NULL, CLSCTX_INPROC_SERVER, + &IID_IUnknown, (void **)&unk); + ok(hr == S_OK, "Got hr %#x.\n", hr); + refcount = get_refcount(unk); + ok(refcount == expected_refcount, "Got refcount: %d, expected %d.\n", refcount, expected_refcount); + refcount = get_refcount(manager); + ok(refcount == expected_refcount, "Got refcount: %d, expected %d.\n", refcount, expected_refcount); + + expected_refcount++; + hr = CoCreateInstance(&CLSID_SharedPropertyGroupManager, NULL, CLSCTX_INPROC_SERVER, + &IID_IDispatch, (void **)&dispatch); + ok(hr == S_OK, "Got hr %#x.\n", hr); + refcount = get_refcount(dispatch); + ok(refcount == expected_refcount, "Got refcount: %d, expected %d.\n", refcount, expected_refcount); + refcount = get_refcount(manager); + ok(refcount == expected_refcount, "Got refcount: %d, expected %d.\n", refcount, expected_refcount); + + IDispatch_Release(dispatch); + IUnknown_Release(unk); + ISharedPropertyGroupManager_Release(manager); +} You only need to create for let's say IUnknown and query result, you then can expect that CoCreateInstance() will succeed for supported interfaces. Does this have a test for single instance?
+ [ + object, + hidden, + local, + uuid(2a005c01-a5de-11cf-9e66-00aa00a3f464), + pointer_default(unique) + ] + interface ISharedProperty : IDispatch + { + [id(0x00000000), propget] + HRESULT Value([out, retval] VARIANT *value); + [id(0x00000000), propput] + HRESULT Value([in] VARIANT value); + }; This could be DISPID_VALUE. And no need for trailing semicolon for interfaces.
+ [ + object, + hidden, + local, + uuid(2a005c0d-a5de-11cf-9e66-00aa00a3f464), + pointer_default(unique) + ] + interface ISharedPropertyGroupManager : IDispatch + { + [id(0x00000001)] + HRESULT CreatePropertyGroup([in] BSTR name, [in, out] LONG *isolation, [in, out] LONG *release, + [out] VARIANT_BOOL *exists, [out, retval] ISharedPropertyGroup **group); + [id(0x00000002), propget] + HRESULT Group([in] BSTR name, [out, retval] ISharedPropertyGroup **group); + [id(0xfffffffc), propget] + HRESULT _NewEnum([out, retval] IUnknown **retval); + }; Similar this one is DISPID_NEWENUM.