From d36b8350d9b04de2b50a76085e47bef059f8f09f Mon Sep 17 00:00:00 2001 From: Nikolay Sivov Date: Sun, 3 Nov 2019 22:30:56 +0300 Subject: [PATCH] comsvcs: Add a stub for "new" moniker. Signed-off-by: Nikolay Sivov Signed-off-by: Alexandre Julliard --- dlls/comsvcs/Makefile.in | 1 + dlls/comsvcs/comsvcs_classes.idl | 29 +++ dlls/comsvcs/main.c | 354 ++++++++++++++++++++++++++++++- dlls/comsvcs/tests/comsvcs.c | 100 +++++++++ 4 files changed, 480 insertions(+), 4 deletions(-) create mode 100644 dlls/comsvcs/comsvcs_classes.idl diff --git a/dlls/comsvcs/Makefile.in b/dlls/comsvcs/Makefile.in index 44c08ffc110..7845400cb2e 100644 --- a/dlls/comsvcs/Makefile.in +++ b/dlls/comsvcs/Makefile.in @@ -8,4 +8,5 @@ C_SRCS = \ main.c IDL_SRCS = \ + comsvcs_classes.idl \ comsvcs_tlb.idl diff --git a/dlls/comsvcs/comsvcs_classes.idl b/dlls/comsvcs/comsvcs_classes.idl new file mode 100644 index 00000000000..ccda14048ef --- /dev/null +++ b/dlls/comsvcs/comsvcs_classes.idl @@ -0,0 +1,29 @@ +/* + * Copyright 2019 Nikolay Sivov + * + * 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 + */ +#pragma makedep register + +[ + uuid(ecabafc6-7f19-11d2-978e-0000f8757e2a), + progid("new"), + helpstring("New Moniker"), + threading(both) +] +coclass NewMoniker +{ + [default] interface IMoniker; +} diff --git a/dlls/comsvcs/main.c b/dlls/comsvcs/main.c index 736608e3273..ae09094d30e 100644 --- a/dlls/comsvcs/main.c +++ b/dlls/comsvcs/main.c @@ -29,6 +29,8 @@ #include "comsvcs.h" #include "wine/heap.h" #include "wine/debug.h" +#include "initguid.h" +#include "comsvcs_classes.h" WINE_DEFAULT_DEBUG_CHANNEL(comsvcs); @@ -49,6 +51,12 @@ typedef struct holder IDispenserDriver *driver; } holder; +struct new_moniker +{ + IMoniker IMoniker_iface; + LONG refcount; +}; + static inline dispensermanager *impl_from_IDispenserManager(IDispenserManager *iface) { return CONTAINING_RECORD(iface, dispensermanager, IDispenserManager_iface); @@ -59,6 +67,11 @@ static inline holder *impl_from_IHolder(IHolder *iface) return CONTAINING_RECORD(iface, holder, IHolder_iface); } +static struct new_moniker *impl_from_IMoniker(IMoniker *iface) +{ + return CONTAINING_RECORD(iface, struct new_moniker, IMoniker_iface); +} + static HRESULT WINAPI holder_QueryInterface(IHolder *iface, REFIID riid, void **object) { holder *This = impl_from_IHolder(iface); @@ -325,7 +338,8 @@ struct IDispenserManagerVtbl dismanager_vtbl = dismanager_GetContext }; -static HRESULT WINAPI comsvcscf_CreateInstance(IClassFactory *cf,IUnknown* outer, REFIID riid,void **object) +static HRESULT WINAPI dispenser_manager_cf_CreateInstance(IClassFactory *iface, IUnknown* outer, REFIID riid, + void **object) { dispensermanager *dismanager; HRESULT ret; @@ -401,26 +415,358 @@ static HRESULT WINAPI comsvcscf_LockServer(IClassFactory *iface, BOOL fLock) return S_OK; } -static const struct IClassFactoryVtbl comsvcscf_vtbl = +static const IClassFactoryVtbl comsvcscf_vtbl = { comsvcscf_QueryInterface, comsvcscf_AddRef, comsvcscf_Release, - comsvcscf_CreateInstance, + dispenser_manager_cf_CreateInstance, + comsvcscf_LockServer +}; + +static HRESULT WINAPI new_moniker_QueryInterface(IMoniker* iface, REFIID riid, void **obj) +{ + TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj); + + *obj = NULL; + + if (IsEqualIID(&IID_IUnknown, riid) || + IsEqualIID(&IID_IPersist, riid) || + IsEqualIID(&IID_IPersistStream, riid) || + IsEqualIID(&IID_IMoniker, riid)) + { + *obj = iface; + } + + if (*obj) + { + IUnknown_AddRef((IUnknown *)*obj); + return S_OK; + } + + WARN("Unsupported interface %s.\n", debugstr_guid(riid)); + return E_NOINTERFACE; +} + +static ULONG WINAPI new_moniker_AddRef(IMoniker* iface) +{ + struct new_moniker *moniker = impl_from_IMoniker(iface); + ULONG refcount = InterlockedIncrement(&moniker->refcount); + + TRACE("%p, refcount %u.\n", iface, refcount); + + return refcount; +} + +static ULONG WINAPI new_moniker_Release(IMoniker* iface) +{ + struct new_moniker *moniker = impl_from_IMoniker(iface); + ULONG refcount = InterlockedDecrement(&moniker->refcount); + + TRACE("%p, refcount %u.\n", iface, refcount); + + if (!refcount) + heap_free(moniker); + + return refcount; +} + +static HRESULT WINAPI new_moniker_GetClassID(IMoniker *iface, CLSID *clsid) +{ + FIXME("%p, %p.\n", iface, clsid); + + return E_NOTIMPL; +} + +static HRESULT WINAPI new_moniker_IsDirty(IMoniker* iface) +{ + FIXME("%p.\n", iface); + + return E_NOTIMPL; +} + +static HRESULT WINAPI new_moniker_Load(IMoniker *iface, IStream *stream) +{ + FIXME("%p, %p.\n", iface, stream); + + return E_NOTIMPL; +} + +static HRESULT WINAPI new_moniker_Save(IMoniker *iface, IStream *stream, BOOL clear_dirty) +{ + FIXME("%p, %p, %d.\n", iface, stream, clear_dirty); + + return E_NOTIMPL; +} + +static HRESULT WINAPI new_moniker_GetSizeMax(IMoniker *iface, ULARGE_INTEGER *size) +{ + FIXME("%p, %p.\n", iface, size); + + return E_NOTIMPL; +} + +static HRESULT WINAPI new_moniker_BindToObject(IMoniker *iface, IBindCtx *pbc, IMoniker *pmkToLeft, + REFIID riid, void **ret) +{ + FIXME("%p, %p, %p, %s, %p.\n", iface, pbc, pmkToLeft, debugstr_guid(riid), ret); + + return E_NOTIMPL; +} + +static HRESULT WINAPI new_moniker_BindToStorage(IMoniker *iface, IBindCtx *pbc, IMoniker *pmkToLeft, REFIID riid, + void **ret) +{ + FIXME("%p, %p, %p, %s, %p.\n", iface, pbc, pmkToLeft, debugstr_guid(riid), ret); + + return E_NOTIMPL; +} + +static HRESULT WINAPI new_moniker_Reduce(IMoniker *iface, IBindCtx *pbc, DWORD flags, IMoniker **ppmkToLeft, + IMoniker **ret) +{ + FIXME("%p, %p, %d, %p, %p.\n", iface, pbc, flags, ppmkToLeft, ret); + + return E_NOTIMPL; +} + +static HRESULT WINAPI new_moniker_ComposeWith(IMoniker *iface, IMoniker *mkRight, BOOL fOnlyIfNotGeneric, + IMoniker **ret) +{ + FIXME("%p, %p, %d, %p.\n", iface, mkRight, fOnlyIfNotGeneric, ret); + + return E_NOTIMPL; +} + +static HRESULT WINAPI new_moniker_Enum(IMoniker *iface, BOOL forward, IEnumMoniker **enum_moniker) +{ + FIXME("%p, %d, %p.\n", iface, forward, enum_moniker); + + return E_NOTIMPL; +} + +static HRESULT WINAPI new_moniker_IsEqual(IMoniker *iface, IMoniker *other_moniker) +{ + FIXME("%p, %p.\n", iface, other_moniker); + + return E_NOTIMPL; +} + +static HRESULT WINAPI new_moniker_Hash(IMoniker *iface, DWORD *hash) +{ + FIXME("%p, %p.\n", iface, hash); + + return E_NOTIMPL; +} + +static HRESULT WINAPI new_moniker_IsRunning(IMoniker* iface, IBindCtx *pbc, IMoniker *pmkToLeft, + IMoniker *pmkNewlyRunning) +{ + FIXME("%p, %p, %p, %p.\n", iface, pbc, pmkToLeft, pmkNewlyRunning); + + return E_NOTIMPL; +} + +static HRESULT WINAPI new_moniker_GetTimeOfLastChange(IMoniker *iface, IBindCtx *pbc, IMoniker *pmkToLeft, + FILETIME *itemtime) +{ + FIXME("%p, %p, %p, %p.\n", iface, pbc, pmkToLeft, itemtime); + + return E_NOTIMPL; +} + +static HRESULT WINAPI new_moniker_Inverse(IMoniker *iface, IMoniker **inverse) +{ + FIXME("%p, %p.\n", iface, inverse); + + return E_NOTIMPL; +} + +static HRESULT WINAPI new_moniker_CommonPrefixWith(IMoniker *iface, IMoniker *other, IMoniker **ret) +{ + FIXME("%p, %p, %p.\n", iface, other, ret); + + return E_NOTIMPL; +} + +static HRESULT WINAPI new_moniker_RelativePathTo(IMoniker *iface, IMoniker *other, IMoniker **ret) +{ + FIXME("%p, %p, %p.\n", iface, other, ret); + + return E_NOTIMPL; +} + +static HRESULT WINAPI new_moniker_GetDisplayName(IMoniker *iface, IBindCtx *pbc, IMoniker *pmkToLeft, + LPOLESTR *name) +{ + FIXME("%p, %p, %p, %p.\n", iface, pbc, pmkToLeft, name); + + return E_NOTIMPL; +} + +static HRESULT WINAPI new_moniker_ParseDisplayName(IMoniker *iface, IBindCtx *pbc, IMoniker *pmkToLeft, + LPOLESTR name, ULONG *eaten, IMoniker **ret) +{ + FIXME("%p, %p, %p, %s, %p, %p.\n", iface, pbc, pmkToLeft, debugstr_w(name), eaten, ret); + + return E_NOTIMPL; +} + +static HRESULT WINAPI new_moniker_IsSystemMoniker(IMoniker *iface, DWORD *moniker_type) +{ + FIXME("%p, %p.\n", iface, moniker_type); + + return E_NOTIMPL; +} + +static const IMonikerVtbl new_moniker_vtbl = +{ + new_moniker_QueryInterface, + new_moniker_AddRef, + new_moniker_Release, + new_moniker_GetClassID, + new_moniker_IsDirty, + new_moniker_Load, + new_moniker_Save, + new_moniker_GetSizeMax, + new_moniker_BindToObject, + new_moniker_BindToStorage, + new_moniker_Reduce, + new_moniker_ComposeWith, + new_moniker_Enum, + new_moniker_IsEqual, + new_moniker_Hash, + new_moniker_IsRunning, + new_moniker_GetTimeOfLastChange, + new_moniker_Inverse, + new_moniker_CommonPrefixWith, + new_moniker_RelativePathTo, + new_moniker_GetDisplayName, + new_moniker_ParseDisplayName, + new_moniker_IsSystemMoniker +}; + +static HRESULT WINAPI new_moniker_parse_QueryInterface(IParseDisplayName *iface, REFIID riid, void **obj) +{ + TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj); + + if (IsEqualIID(riid, &IID_IParseDisplayName) || + IsEqualIID(riid, &IID_IUnknown)) + { + *obj = iface; + IParseDisplayName_AddRef(iface); + return S_OK; + } + + *obj = NULL; + WARN("Unsupported interface %s.\n", debugstr_guid(riid)); + return E_NOINTERFACE; +} + +static ULONG WINAPI new_moniker_parse_AddRef(IParseDisplayName *iface) +{ + return 2; +} + +static ULONG WINAPI new_moniker_parse_Release(IParseDisplayName *iface) +{ + return 1; +} + +static HRESULT WINAPI new_moniker_parse_ParseDisplayName(IParseDisplayName *iface, IBindCtx *pbc, LPOLESTR name, + ULONG *eaten, IMoniker **ret) +{ + struct new_moniker *moniker; + + FIXME("%p, %p, %s, %p, %p.\n", iface, pbc, debugstr_w(name), eaten, ret); + + moniker = heap_alloc_zero(sizeof(*moniker)); + if (!moniker) + return E_OUTOFMEMORY; + + moniker->IMoniker_iface.lpVtbl = &new_moniker_vtbl; + moniker->refcount = 1; + + *ret = &moniker->IMoniker_iface; + + *eaten = lstrlenW(name); + + return S_OK; +} + +static const IParseDisplayNameVtbl new_moniker_parse_vtbl = +{ + new_moniker_parse_QueryInterface, + new_moniker_parse_AddRef, + new_moniker_parse_Release, + new_moniker_parse_ParseDisplayName, +}; + +static IParseDisplayName new_moniker_parse = { &new_moniker_parse_vtbl }; + +static HRESULT WINAPI new_moniker_cf_QueryInterface(IClassFactory *iface, REFIID riid, void **obj) +{ + TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj); + + *obj = NULL; + + if (IsEqualGUID(&IID_IUnknown, riid) || + IsEqualGUID(&IID_IClassFactory, riid)) + { + *obj = iface; + } + else if (IsEqualIID(&IID_IParseDisplayName, riid)) + { + *obj = &new_moniker_parse; + } + + if (*obj) + { + IUnknown_AddRef((IUnknown *)*obj); + return S_OK; + } + + WARN("Unsupported interface %s.\n", debugstr_guid(riid)); + return E_NOINTERFACE; +} + +static HRESULT WINAPI new_moniker_cf_CreateInstance(IClassFactory *iface, IUnknown* outer, REFIID riid, void **object) +{ + TRACE("%p, %p, %s, %p.\n", iface, outer, debugstr_guid(riid), object); + + if (outer) + FIXME("Aggregation is not supported.\n"); + + return IParseDisplayName_QueryInterface(&new_moniker_parse, riid, object); +} + +static const IClassFactoryVtbl newmoniker_cf_vtbl = +{ + new_moniker_cf_QueryInterface, + comsvcscf_AddRef, + comsvcscf_Release, + new_moniker_cf_CreateInstance, comsvcscf_LockServer }; static IClassFactory DispenserManageFactory = { &comsvcscf_vtbl }; +static IClassFactory NewMonikerFactory = { &newmoniker_cf_vtbl }; /****************************************************************** * DllGetClassObject */ HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, void **ppv) { - if(IsEqualGUID(&CLSID_DispenserManager, rclsid)) { + if(IsEqualGUID(&CLSID_DispenserManager, rclsid)) + { TRACE("(CLSID_DispenserManager %s %p)\n", debugstr_guid(riid), ppv); return IClassFactory_QueryInterface(&DispenserManageFactory, riid, ppv); } + else if (IsEqualGUID(&CLSID_NewMoniker, rclsid)) + { + TRACE("(CLSID_NewMoniker %s %p)\n", debugstr_guid(riid), ppv); + return IClassFactory_QueryInterface(&NewMonikerFactory, riid, ppv); + } FIXME("%s %s %p\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv); return CLASS_E_CLASSNOTAVAILABLE; diff --git a/dlls/comsvcs/tests/comsvcs.c b/dlls/comsvcs/tests/comsvcs.c index 77d32243661..68760afd913 100644 --- a/dlls/comsvcs/tests/comsvcs.c +++ b/dlls/comsvcs/tests/comsvcs.c @@ -267,6 +267,105 @@ static void create_dispenser(void) IDispenserManager_Release(dispenser); } +static void test_new_moniker(void) +{ + IMoniker *moniker, *inverse, *class_moniker; + DWORD moniker_type; + IBindCtx *bindctx; + FILETIME filetime; + DWORD hash, eaten; + IUnknown *obj, *obj2; + CLSID clsid; + HRESULT hr; + + hr = CreateBindCtx(0, &bindctx); + ok(hr == S_OK, "Failed to create bind context, hr %#x.\n", hr); + + eaten = 0; + hr = MkParseDisplayName(bindctx, L"new:20d04fe0-3aea-1069-a2d8-08002b30309d", &eaten, &moniker); + ok(hr == S_OK, "Failed to parse display name, hr %#x.\n", hr); + ok(eaten == 40, "Unexpected eaten length %u.\n", eaten); + + hr = IMoniker_QueryInterface(moniker, &IID_IParseDisplayName, (void **)&obj); + ok(hr == E_NOINTERFACE, "Unexpected hr %#x.\n", hr); + + /* Object creation. */ + hr = CLSIDFromProgID(L"new", &clsid); + ok(hr == S_OK, "Failed to get clsid, hr %#x.\n", hr); + + hr = CreateClassMoniker(&clsid, &class_moniker); + ok(hr == S_OK, "Failed to create class moniker, hr %#x.\n", hr); + + hr = IMoniker_BindToObject(class_moniker, bindctx, NULL, &IID_IParseDisplayName, (void **)&obj); + ok(hr == S_OK, "Failed to get parsing interface, hr %#x.\n", hr); + IUnknown_Release(obj); + + hr = IMoniker_BindToObject(class_moniker, bindctx, NULL, &IID_IClassFactory, (void **)&obj); + ok(hr == S_OK, "Failed to get parsing interface, hr %#x.\n", hr); + IUnknown_Release(obj); + + hr = CoGetClassObject(&clsid, CLSCTX_INPROC_SERVER, NULL, &IID_IParseDisplayName, (void **)&obj); + ok(hr == S_OK, "Failed to get parsing interface, hr %#x.\n", hr); + IUnknown_Release(obj); + + hr = CoGetClassObject(&clsid, CLSCTX_INPROC_SERVER, NULL, &IID_IClassFactory, (void **)&obj); + ok(hr == S_OK, "Failed to get parsing interface, hr %#x.\n", hr); + + hr = IUnknown_QueryInterface(obj, &IID_IParseDisplayName, (void **)&obj2); + ok(hr == S_OK, "Failed to get parsing interface, hr %#x.\n", hr); + IUnknown_Release(obj); + + IMoniker_Release(class_moniker); + + /* Hashing */ + hash = 0; + hr = IMoniker_Hash(moniker, &hash); +todo_wine { + ok(hr == S_OK, "Failed to get a hash, hr %#x.\n", hr); + ok(hash == 0x20d04fe0, "Unexpected hash value %#x.\n", hash); +} + moniker_type = MKSYS_CLASSMONIKER; + hr = IMoniker_IsSystemMoniker(moniker, &moniker_type); +todo_wine { + ok(hr == S_FALSE || broken(hr == S_OK) /* XP */, "Unexpected hr %#x.\n", hr); + ok(moniker_type == MKSYS_NONE, "Unexpected moniker type %d.\n", moniker_type); +} + hr = IMoniker_IsRunning(moniker, NULL, NULL, NULL); +todo_wine + ok(hr == S_FALSE, "Unexpected hr %#x.\n", hr); + + hr = IMoniker_IsRunning(moniker, bindctx, NULL, NULL); +todo_wine + ok(hr == S_FALSE, "Unexpected hr %#x.\n", hr); + + hr = IMoniker_GetTimeOfLastChange(moniker, bindctx, NULL, &filetime); +todo_wine + ok(hr == MK_E_UNAVAILABLE, "Unexpected hr %#x.\n", hr); + + hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&obj); +todo_wine + ok(hr == S_OK, "Failed to bind to object, hr %#x.\n", hr); + if (SUCCEEDED(hr)) + IUnknown_Release(obj); + + hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IUnknown, (void **)&obj); +todo_wine + ok(hr == MK_E_NOSTORAGE, "Unexpected hr %#x.\n", hr); + + hr = IMoniker_Inverse(moniker, &inverse); +todo_wine + ok(hr == S_OK, "Failed to create inverse moniker, hr %#x.\n", hr); +if (SUCCEEDED(hr)) +{ + moniker_type = MKSYS_NONE; + hr = IMoniker_IsSystemMoniker(inverse, &moniker_type); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(moniker_type == MKSYS_ANTIMONIKER, "Unexpected moniker type %d.\n", moniker_type); + IMoniker_Release(inverse); +} + IMoniker_Release(moniker); + IBindCtx_Release(bindctx); +} START_TEST(comsvcs) { @@ -278,6 +377,7 @@ START_TEST(comsvcs) return; create_dispenser(); + test_new_moniker(); CoUninitialize(); }