diff --git a/dlls/comsvcs/Makefile.in b/dlls/comsvcs/Makefile.in index 8e6a9bac4dd..22090938b52 100644 --- a/dlls/comsvcs/Makefile.in +++ b/dlls/comsvcs/Makefile.in @@ -5,7 +5,8 @@ IMPORTS = ole32 uuid EXTRADLLFLAGS = -Wb,--prefer-native C_SRCS = \ - main.c + main.c \ + property.c IDL_SRCS = \ comsvcs_classes.idl \ diff --git a/dlls/comsvcs/comsvcs_private.h b/dlls/comsvcs/comsvcs_private.h new file mode 100644 index 00000000000..c09c2174e0e --- /dev/null +++ b/dlls/comsvcs/comsvcs_private.h @@ -0,0 +1,34 @@ +/* + * Copyright 2021 Jactry Zeng for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef _COMSVCS_PRIVATE_H_ +#define _COMSVCS_PRIVATE_H_ + +#define COBJMACROS + +#include + +#include "windef.h" +#include "winbase.h" +#include "ole2.h" +#include "rpcproxy.h" +#include "comsvcs.h" + +HRESULT WINAPI group_manager_create(IClassFactory *iface, IUnknown *outer, REFIID riid, void **out); + +#endif diff --git a/dlls/comsvcs/main.c b/dlls/comsvcs/main.c index c95e8dad8f0..797e2db97db 100644 --- a/dlls/comsvcs/main.c +++ b/dlls/comsvcs/main.c @@ -18,15 +18,7 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ -#define COBJMACROS - -#include - -#include "windef.h" -#include "winbase.h" -#include "ole2.h" -#include "rpcproxy.h" -#include "comsvcs.h" +#include "comsvcs_private.h" #include "wine/heap.h" #include "wine/debug.h" #include "initguid.h" @@ -995,8 +987,18 @@ static const IClassFactoryVtbl newmoniker_cf_vtbl = comsvcscf_LockServer }; +static const IClassFactoryVtbl group_manager_cf_vtbl = +{ + comsvcscf_QueryInterface, + comsvcscf_AddRef, + comsvcscf_Release, + group_manager_create, + comsvcscf_LockServer +}; + static IClassFactory DispenserManageFactory = { &comsvcscf_vtbl }; static IClassFactory NewMonikerFactory = { &newmoniker_cf_vtbl }; +static IClassFactory GroupManagerFactory = { &group_manager_cf_vtbl }; /****************************************************************** * DllGetClassObject @@ -1013,6 +1015,11 @@ HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, void **ppv) TRACE("(CLSID_NewMoniker %s %p)\n", debugstr_guid(riid), ppv); return IClassFactory_QueryInterface(&NewMonikerFactory, riid, ppv); } + else if (IsEqualGUID(&CLSID_SharedPropertyGroupManager, rclsid)) + { + TRACE("(CLSID_SharedPropertyGroupManager %s %p)\n", debugstr_guid(riid), ppv); + return IClassFactory_QueryInterface(&GroupManagerFactory, riid, ppv); + } FIXME("%s %s %p\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv); return CLASS_E_CLASSNOTAVAILABLE; diff --git a/dlls/comsvcs/property.c b/dlls/comsvcs/property.c new file mode 100644 index 00000000000..4dc6e1d9a46 --- /dev/null +++ b/dlls/comsvcs/property.c @@ -0,0 +1,166 @@ +/* + * Copyright 2021 Jactry Zeng for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "comsvcs_private.h" +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(comsvcs); + +struct group_manager +{ + ISharedPropertyGroupManager ISharedPropertyGroupManager_iface; + LONG refcount; +}; + +static struct group_manager *group_manager = NULL; + +static inline struct group_manager *impl_from_ISharedPropertyGroupManager(ISharedPropertyGroupManager *iface) +{ + return CONTAINING_RECORD(iface, struct group_manager, ISharedPropertyGroupManager_iface); +} + +static HRESULT WINAPI group_manager_QueryInterface(ISharedPropertyGroupManager *iface, REFIID riid, void **out) +{ + struct group_manager *manager = impl_from_ISharedPropertyGroupManager(iface); + + TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out); + + if (IsEqualGUID(riid, &IID_IUnknown) + || IsEqualGUID(riid, &IID_IDispatch) + || IsEqualGUID(riid, &IID_ISharedPropertyGroupManager)) + { + *out = &manager->ISharedPropertyGroupManager_iface; + IUnknown_AddRef((IUnknown *)*out); + return S_OK; + } + + WARN("%s not implemented.\n", debugstr_guid(riid)); + *out = NULL; + return E_NOINTERFACE; +} + +static ULONG WINAPI group_manager_AddRef(ISharedPropertyGroupManager *iface) +{ + struct group_manager *manager = impl_from_ISharedPropertyGroupManager(iface); + ULONG refcount = InterlockedIncrement(&manager->refcount); + + TRACE("%p increasing refcount to %u.\n", iface, refcount); + + return refcount; +} + +static ULONG WINAPI group_manager_Release(ISharedPropertyGroupManager *iface) +{ + struct group_manager *manager = impl_from_ISharedPropertyGroupManager(iface); + ULONG refcount = InterlockedDecrement(&manager->refcount); + + TRACE("%p decreasing refcount to %u.\n", iface, refcount); + + return refcount; +} + +static HRESULT WINAPI group_manager_GetTypeInfoCount(ISharedPropertyGroupManager *iface, UINT *info) +{ + FIXME("iface %p, info %p: stub.\n", iface, info); + return E_NOTIMPL; +} + +static HRESULT WINAPI group_manager_GetTypeInfo(ISharedPropertyGroupManager *iface, UINT index, LCID lcid, + ITypeInfo **info) +{ + FIXME("iface %p, index %u, lcid %u, info %p: stub.\n", iface, index, lcid, info); + return E_NOTIMPL; +} + +static HRESULT WINAPI group_manager_GetIDsOfNames(ISharedPropertyGroupManager *iface, REFIID riid, + LPOLESTR *names, UINT count, LCID lcid, DISPID *dispid) +{ + FIXME("iface %p, riid %s, names %p, count %u, lcid %u, dispid %p: stub.\n", + iface, debugstr_guid(riid), names, count, lcid, dispid); + + return E_NOTIMPL; +} + +static HRESULT WINAPI group_manager_Invoke(ISharedPropertyGroupManager *iface, DISPID member, REFIID riid, + LCID lcid, WORD flags, DISPPARAMS *params, VARIANT *result, EXCEPINFO *except, UINT *argerr) +{ + FIXME("iface %p, member %u, riid %s, lcid %u, flags %x, params %p, result %p, except %p, argerr %p: stub.\n", + iface, member, debugstr_guid(riid), lcid, flags, params, result, except, argerr); + return E_NOTIMPL; +} + +static HRESULT WINAPI group_manager_CreatePropertyGroup(ISharedPropertyGroupManager *iface, BSTR name, + LONG *isolation, LONG *release, VARIANT_BOOL *exists, ISharedPropertyGroup **group) +{ + FIXME("iface %p, name %s, isolation %p, release %p, exists %p, group %p: stub.\n", + iface, debugstr_w(name), isolation, release, exists, group); + return E_NOTIMPL; +} + +static HRESULT WINAPI group_manager_get_Group(ISharedPropertyGroupManager *iface, BSTR name, + ISharedPropertyGroup **group) +{ + FIXME("iface %p, name %s, group %p: stub.\n", iface, debugstr_w(name), group); + return E_NOTIMPL; +} + +static HRESULT WINAPI group_manager_get__NewEnum(ISharedPropertyGroupManager *iface, IUnknown **retval) +{ + FIXME("iface %p, retval %p: stub.\n", iface, retval); + return E_NOTIMPL; +} + +static const ISharedPropertyGroupManagerVtbl group_manager_vtbl = +{ + group_manager_QueryInterface, + group_manager_AddRef, + group_manager_Release, + group_manager_GetTypeInfoCount, + group_manager_GetTypeInfo, + group_manager_GetIDsOfNames, + group_manager_Invoke, + group_manager_CreatePropertyGroup, + group_manager_get_Group, + group_manager_get__NewEnum +}; + +HRESULT WINAPI group_manager_create(IClassFactory *iface, IUnknown *outer, REFIID riid, void **out) +{ + struct group_manager *manager; + + if (outer) + return CLASS_E_NOAGGREGATION; + + if (!group_manager) + { + manager = malloc(sizeof(*manager)); + if (!manager) + { + *out = NULL; + return E_OUTOFMEMORY; + } + manager->ISharedPropertyGroupManager_iface.lpVtbl = &group_manager_vtbl; + manager->refcount = 1; + + if (InterlockedCompareExchangePointer((void **)&group_manager, manager, NULL)) + { + free(manager); + } + } + return ISharedPropertyGroupManager_QueryInterface(&group_manager->ISharedPropertyGroupManager_iface, riid, out); +} diff --git a/dlls/comsvcs/tests/Makefile.in b/dlls/comsvcs/tests/Makefile.in index 86da9fda662..1d9146ba5b6 100644 --- a/dlls/comsvcs/tests/Makefile.in +++ b/dlls/comsvcs/tests/Makefile.in @@ -2,4 +2,5 @@ TESTDLL = comsvcs.dll IMPORTS = uuid oleaut32 ole32 C_SRCS = \ - comsvcs.c + comsvcs.c \ + property.c diff --git a/dlls/comsvcs/tests/property.c b/dlls/comsvcs/tests/property.c new file mode 100644 index 00000000000..7be62987507 --- /dev/null +++ b/dlls/comsvcs/tests/property.c @@ -0,0 +1,115 @@ +/* + * Copyright 2021 Jactry Zeng for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#define COBJMACROS + +#include + +#include "windef.h" +#include "winbase.h" +#include "comsvcs.h" + +#include "wine/test.h" + +static ULONG get_refcount(void *iface) +{ + IUnknown *unknown = iface; + IUnknown_AddRef(unknown); + return IUnknown_Release(unknown); +} + +static HRESULT WINAPI outer_QueryInterface(IUnknown *iface, REFIID iid, void **out) +{ + ok(0, "Unexpected call.\n"); + return E_NOINTERFACE; +} + +static ULONG WINAPI outer_AddRef(IUnknown *iface) +{ + ok(0, "Unexpected call.\n"); + return 1; +} + +static ULONG WINAPI outer_Release(IUnknown *iface) +{ + ok(0, "Unexpected call.\n"); + return 0; +} + +static const IUnknownVtbl outer_vtbl = +{ + outer_QueryInterface, + outer_AddRef, + outer_Release, +}; + +static IUnknown test_outer = {&outer_vtbl}; + +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_IUnknown, (void **)&unk); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + expected_refcount = get_refcount(unk) + 1; + hr = IUnknown_QueryInterface(unk, &IID_ISharedPropertyGroupManager, (void **)&manager); + ok(hr == S_OK, "Got hr %#x.\n", hr); + refcount = get_refcount(unk); + ok(refcount == expected_refcount, "Got refcount: %u, expected %u.\n", refcount, expected_refcount); + + 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); + ok(manager1 == manager, "Got wrong pointer: %p.\n", manager1); + refcount = get_refcount(manager1); + ok(refcount == expected_refcount, "Got refcount: %u, expected %u.\n", refcount, expected_refcount); + refcount = get_refcount(manager); + ok(refcount == expected_refcount, "Got refcount: %u, expected %u.\n", refcount, expected_refcount); + ISharedPropertyGroupManager_Release(manager1); + + hr = IUnknown_QueryInterface(unk, &IID_IDispatch, (void **)&dispatch); + ok(hr == S_OK, "Got hr %#x.\n", hr); + refcount = get_refcount(dispatch); + ok(refcount == expected_refcount, "Got refcount: %u, expected %u.\n", refcount, expected_refcount); + refcount = get_refcount(manager); + ok(refcount == expected_refcount, "Got refcount: %u, expected %u.\n", refcount, expected_refcount); + + IDispatch_Release(dispatch); + IUnknown_Release(unk); + ISharedPropertyGroupManager_Release(manager); +} + +START_TEST(property) +{ + CoInitialize(NULL); + + test_interfaces(); + + CoUninitialize(); +}