test_objref_moniker() is a copy of test_pointer_moniker() with appropriate changes.
Signed-off-by: Dmitry Timoshkov dmitry@baikal.ru --- dlls/ole32/moniker.h | 4 +- dlls/ole32/ole32.spec | 2 +- dlls/ole32/ole32_objidl.idl | 6 + dlls/ole32/oleproxy.c | 13 +++ dlls/ole32/pointermoniker.c | 186 ++++++++++++++++++++++++++++-- dlls/ole32/tests/moniker.c | 220 +++++++++++++++++++++++++++++++++++- include/objidl.idl | 5 +- 7 files changed, 423 insertions(+), 13 deletions(-)
diff --git a/dlls/ole32/moniker.h b/dlls/ole32/moniker.h index 8549bd46c1e..2106e374394 100644 --- a/dlls/ole32/moniker.h +++ b/dlls/ole32/moniker.h @@ -26,15 +26,17 @@ DEFINE_OLEGUID( CLSID_FileMoniker, 0x303, 0, 0 ); DEFINE_OLEGUID( CLSID_ItemMoniker, 0x304, 0, 0 ); DEFINE_OLEGUID( CLSID_AntiMoniker, 0x305, 0, 0 ); +DEFINE_OLEGUID( CLSID_PointerMoniker, 0x306, 0, 0 ); DEFINE_OLEGUID( CLSID_CompositeMoniker, 0x309, 0, 0 ); DEFINE_OLEGUID( CLSID_ClassMoniker, 0x31a, 0, 0 ); -DEFINE_OLEGUID( CLSID_PointerMoniker, 0x306, 0, 0 ); +DEFINE_OLEGUID( CLSID_ObjrefMoniker, 0x327, 0, 0 );
HRESULT WINAPI FileMoniker_CreateInstance(IClassFactory *iface, IUnknown *pUnk, REFIID riid, void **ppv); HRESULT WINAPI ItemMoniker_CreateInstance(IClassFactory *iface, IUnknown *pUnk, REFIID riid, void **ppv); HRESULT WINAPI AntiMoniker_CreateInstance(IClassFactory *iface, IUnknown *pUnk, REFIID riid, void **ppv); HRESULT WINAPI CompositeMoniker_CreateInstance(IClassFactory *iface, IUnknown *pUnk, REFIID riid, void **ppv); HRESULT WINAPI ClassMoniker_CreateInstance(IClassFactory *iface, IUnknown *pUnk, REFIID riid, void **ppv); +HRESULT WINAPI ObjrefMoniker_CreateInstance(IClassFactory *iface, IUnknown *pUnk, REFIID riid, void **ppv); HRESULT WINAPI PointerMoniker_CreateInstance(IClassFactory *iface, IUnknown *pUnk, REFIID riid, void **ppv); HRESULT WINAPI ComCat_CreateInstance(IClassFactory *iface, IUnknown *pUnk, REFIID riid, void **ppv);
diff --git a/dlls/ole32/ole32.spec b/dlls/ole32/ole32.spec index 8e73fdd16b4..d9ffd63585c 100644 --- a/dlls/ole32/ole32.spec +++ b/dlls/ole32/ole32.spec @@ -103,7 +103,7 @@ @ stdcall CreateGenericComposite(ptr ptr ptr) @ stdcall CreateILockBytesOnHGlobal(ptr long ptr) @ stdcall CreateItemMoniker(wstr wstr ptr) -@ stub CreateObjrefMoniker +@ stdcall CreateObjrefMoniker(ptr ptr) @ stdcall CreateOleAdviseHolder(ptr) @ stdcall CreatePointerMoniker(ptr ptr) @ stdcall CreateStreamOnHGlobal(ptr long ptr) combase.CreateStreamOnHGlobal diff --git a/dlls/ole32/ole32_objidl.idl b/dlls/ole32/ole32_objidl.idl index 0cc3ccea9e5..97f91224839 100644 --- a/dlls/ole32/ole32_objidl.idl +++ b/dlls/ole32/ole32_objidl.idl @@ -105,6 +105,12 @@ coclass ClassMoniker { interface IMoniker; } ] coclass PSFactoryBuffer { interface IFactoryBuffer; }
+[ + threading(both), + uuid(00000327-0000-0000-c000-000000000046) +] +coclass ObjrefMoniker { interface IMoniker; } + [ helpstring("Component Categories Manager"), threading(both), diff --git a/dlls/ole32/oleproxy.c b/dlls/ole32/oleproxy.c index e40e2b073e5..c429ce02b3b 100644 --- a/dlls/ole32/oleproxy.c +++ b/dlls/ole32/oleproxy.c @@ -137,6 +137,17 @@ static const IClassFactoryVtbl PointerMonikerCFVtbl =
static IClassFactory PointerMonikerCF = { &PointerMonikerCFVtbl };
+static const IClassFactoryVtbl ObjrefMonikerCFVtbl = +{ + ClassFactory_QueryInterface, + ClassFactory_AddRef, + ClassFactory_Release, + ObjrefMoniker_CreateInstance, + ClassFactory_LockServer +}; + +static IClassFactory ObjrefMonikerCF = { &ObjrefMonikerCFVtbl }; + static const IClassFactoryVtbl ComCatCFVtbl = { ClassFactory_QueryInterface, @@ -198,6 +209,8 @@ HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID iid,LPVOID *ppv) return IClassFactory_QueryInterface(&CompositeMonikerCF, iid, ppv); if (IsEqualCLSID(rclsid, &CLSID_ClassMoniker)) return IClassFactory_QueryInterface(&ClassMonikerCF, iid, ppv); + if (IsEqualCLSID(rclsid, &CLSID_ObjrefMoniker)) + return IClassFactory_QueryInterface(&ObjrefMonikerCF, iid, ppv); if (IsEqualCLSID(rclsid, &CLSID_PointerMoniker)) return IClassFactory_QueryInterface(&PointerMonikerCF, iid, ppv); if (IsEqualGUID(rclsid, &CLSID_StdComponentCategoriesMgr)) diff --git a/dlls/ole32/pointermoniker.c b/dlls/ole32/pointermoniker.c index 051d42aca6d..ea145b8b9c0 100644 --- a/dlls/ole32/pointermoniker.c +++ b/dlls/ole32/pointermoniker.c @@ -1,5 +1,5 @@ /* - * Pointer Moniker Implementation + * Pointer and Objref Monikers Implementation * * Copyright 1999 Noomen Hamza * Copyright 2008 Robert Shearman (for CodeWeavers) @@ -470,13 +470,6 @@ static const IMonikerVtbl VT_PointerMonikerImpl = PointerMonikerImpl_IsSystemMoniker };
-static PointerMonikerImpl *unsafe_impl_from_IMoniker(IMoniker *iface) -{ - if (iface->lpVtbl != &VT_PointerMonikerImpl) - return NULL; - return CONTAINING_RECORD(iface, PointerMonikerImpl, IMoniker_iface); -} - static HRESULT WINAPI pointer_moniker_marshal_QueryInterface(IMarshal *iface, REFIID riid, LPVOID *ppv) { PointerMonikerImpl *moniker = impl_from_IMarshal(iface); @@ -641,3 +634,180 @@ HRESULT WINAPI PointerMoniker_CreateInstance(IClassFactory *iface,
return hr; } + +/* ObjrefMoniker implementation */ + +static HRESULT WINAPI ObjrefMonikerImpl_QueryInterface(IMoniker *iface, REFIID iid, void **obj) +{ + PointerMonikerImpl *moniker = impl_from_IMoniker(iface); + + TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), obj); + + if (!obj) + return E_INVALIDARG; + + *obj = 0; + + if (IsEqualIID(iid, &IID_IUnknown) || + IsEqualIID(iid, &IID_IPersist) || + IsEqualIID(iid, &IID_IPersistStream) || + IsEqualIID(iid, &IID_IMoniker) || + IsEqualGUID(iid, &CLSID_ObjrefMoniker) || + IsEqualGUID(iid, &CLSID_PointerMoniker)) + { + *obj = iface; + } + else if (IsEqualIID(iid, &IID_IMarshal)) + *obj = &moniker->IMarshal_iface; + else + return E_NOINTERFACE; + + IMoniker_AddRef(iface); + + return S_OK; +} + +static HRESULT WINAPI ObjrefMonikerImpl_GetClassID(IMoniker *iface, CLSID *clsid) +{ + TRACE("(%p,%p)\n", iface, clsid); + + if (!clsid) + return E_POINTER; + + *clsid = CLSID_ObjrefMoniker; + return S_OK; +} + +static HRESULT WINAPI ObjrefMonikerImpl_Save(IMoniker *iface, IStream *stream, BOOL dirty) +{ + FIXME("(%p,%p,%d): stub\n", iface, stream, dirty); + return E_NOTIMPL; +} + +static HRESULT WINAPI ObjrefMonikerImpl_Enum(IMoniker *iface, BOOL forward, IEnumMoniker **enummoniker) +{ + TRACE("(%p,%d,%p)\n", iface, forward, enummoniker); + + if (!enummoniker) + return E_POINTER; + + *enummoniker = NULL; + return S_OK; +} + +static HRESULT WINAPI ObjrefMonikerImpl_GetTimeOfLastChange(IMoniker *iface, + IBindCtx *pbc, IMoniker *pmkToLeft, FILETIME *pAntiTime) +{ + TRACE("(%p,%p,%p,%p)\n", iface, pbc, pmkToLeft, pAntiTime); + return MK_E_UNAVAILABLE; +} + +static HRESULT WINAPI ObjrefMonikerImpl_GetDisplayName(IMoniker *iface, IBindCtx *pbc, + IMoniker *pmkToLeft, LPOLESTR *ppszDisplayName) +{ + FIXME("(%p,%p,%p,%p): stub\n", iface, pbc, pmkToLeft, ppszDisplayName); + + if (!ppszDisplayName) + return E_POINTER; + + *ppszDisplayName = NULL; + return E_NOTIMPL; +} + +static HRESULT WINAPI ObjrefMonikerImpl_IsSystemMoniker(IMoniker *iface, DWORD *mksys) +{ + TRACE("(%p,%p)\n", iface, mksys); + + if (!mksys) + return E_POINTER; + + *mksys = MKSYS_OBJREFMONIKER; + return S_OK; +} + +static const IMonikerVtbl VT_ObjrefMonikerImpl = +{ + ObjrefMonikerImpl_QueryInterface, + PointerMonikerImpl_AddRef, + PointerMonikerImpl_Release, + ObjrefMonikerImpl_GetClassID, + PointerMonikerImpl_IsDirty, + PointerMonikerImpl_Load, + ObjrefMonikerImpl_Save, + PointerMonikerImpl_GetSizeMax, + PointerMonikerImpl_BindToObject, + PointerMonikerImpl_BindToStorage, + PointerMonikerImpl_Reduce, + PointerMonikerImpl_ComposeWith, + ObjrefMonikerImpl_Enum, + PointerMonikerImpl_IsEqual, + PointerMonikerImpl_Hash, + PointerMonikerImpl_IsRunning, + ObjrefMonikerImpl_GetTimeOfLastChange, + PointerMonikerImpl_Inverse, + PointerMonikerImpl_CommonPrefixWith, + PointerMonikerImpl_RelativePathTo, + ObjrefMonikerImpl_GetDisplayName, + PointerMonikerImpl_ParseDisplayName, + ObjrefMonikerImpl_IsSystemMoniker +}; + +static PointerMonikerImpl *unsafe_impl_from_IMoniker(IMoniker *iface) +{ + if (iface->lpVtbl != &VT_PointerMonikerImpl && iface->lpVtbl != &VT_ObjrefMonikerImpl) + return NULL; + return CONTAINING_RECORD(iface, PointerMonikerImpl, IMoniker_iface); +} + +/*********************************************************************** + * CreateObjrefMoniker (OLE32.@) + */ +HRESULT WINAPI CreateObjrefMoniker(IUnknown *obj, IMoniker **ret) +{ + PointerMonikerImpl *moniker; + + TRACE("(%p,%p)\n", obj, ret); + + if (!ret) + return E_INVALIDARG; + + moniker = heap_alloc(sizeof(*moniker)); + if (!moniker) + { + *ret = NULL; + return E_OUTOFMEMORY; + } + + moniker->IMoniker_iface.lpVtbl = &VT_ObjrefMonikerImpl; + moniker->IMarshal_iface.lpVtbl = &pointer_moniker_marshal_vtbl; + moniker->refcount = 1; + moniker->pObject = obj; + if (moniker->pObject) + IUnknown_AddRef(moniker->pObject); + + *ret = &moniker->IMoniker_iface; + + return S_OK; +} + +HRESULT WINAPI ObjrefMoniker_CreateInstance(IClassFactory *iface, IUnknown *unk, REFIID iid, void **obj) +{ + IMoniker *moniker; + HRESULT hr; + + TRACE("(%p,%s,%p)\n", unk, debugstr_guid(iid), obj); + + *obj = NULL; + + if (unk) + return CLASS_E_NOAGGREGATION; + + hr = CreateObjrefMoniker(NULL, &moniker); + if (FAILED(hr)) + return hr; + + hr = IMoniker_QueryInterface(moniker, iid, obj); + IMoniker_Release(moniker); + + return hr; +} diff --git a/dlls/ole32/tests/moniker.c b/dlls/ole32/tests/moniker.c index 8d3276651bc..cda4e8bf212 100644 --- a/dlls/ole32/tests/moniker.c +++ b/dlls/ole32/tests/moniker.c @@ -82,9 +82,10 @@ static const CLSID CLSID_TestMoniker = DEFINE_OLEGUID(CLSID_FileMoniker, 0x303, 0, 0); DEFINE_OLEGUID(CLSID_ItemMoniker, 0x304, 0, 0); DEFINE_OLEGUID(CLSID_AntiMoniker, 0x305, 0, 0); +DEFINE_OLEGUID(CLSID_PointerMoniker, 0x306, 0, 0); DEFINE_OLEGUID(CLSID_CompositeMoniker, 0x309, 0, 0); DEFINE_OLEGUID(CLSID_ClassMoniker, 0x31a, 0, 0); -DEFINE_OLEGUID(CLSID_PointerMoniker, 0x306, 0, 0); +DEFINE_OLEGUID(CLSID_ObjrefMoniker, 0x327, 0, 0);
#define TEST_MONIKER_TYPE_TODO(m,t) _test_moniker_type(m, t, TRUE, __LINE__) #define TEST_MONIKER_TYPE(m,t) _test_moniker_type(m, t, FALSE, __LINE__) @@ -3861,7 +3862,7 @@ todo_wine
hr = IMarshal_GetUnmarshalClass(marshal, NULL, NULL, 0, NULL, 0, &clsid); ok(hr == S_OK, "Failed to get class, hr %#x.\n", hr); - ok(IsEqualGUID(&clsid, &CLSID_PointerMoniker), "Unexpected class.\n"); + ok(IsEqualGUID(&clsid, &CLSID_PointerMoniker), "Unexpected class %s.\n", wine_dbgstr_guid(&clsid));
hr = IMarshal_GetMarshalSizeMax(marshal, &IID_IMoniker, NULL, CLSCTX_INPROC, NULL, 0, &size); ok(hr == S_OK, "Failed to get marshal size, hr %#x.\n", hr); @@ -4076,6 +4077,220 @@ todo_wine IMoniker_Release(moniker); }
+static void test_objref_moniker(void) +{ + IMoniker *moniker, *moniker2, *prefix, *inverse, *anti; + struct test_factory factory; + IEnumMoniker *enummoniker; + DWORD hash, size; + HRESULT hr; + IBindCtx *bindctx; + FILETIME filetime; + IUnknown *unknown; + IStream *stream; + IROTData *rotdata; + LPOLESTR display_name; + IMarshal *marshal; + LARGE_INTEGER pos; + CLSID clsid; + + test_factory_init(&factory); + + hr = CreateObjrefMoniker((IUnknown *)&factory.IClassFactory_iface, NULL); + ok(hr == E_INVALIDARG, "CreatePointerMoniker(x, NULL) should have returned E_INVALIDARG instead of 0x%08x\n", hr); + + hr = CreateObjrefMoniker((IUnknown *)&factory.IClassFactory_iface, &moniker); + ok(hr == S_OK, "CreateObjrefMoniker failed: hr %#x.\n", hr); + + hr = IMoniker_QueryInterface(moniker, &IID_IMoniker, NULL); + ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr); + + hr = IMoniker_QueryInterface(moniker, &CLSID_PointerMoniker, (void **)&unknown); + ok(unknown == (IUnknown *)moniker, "Unexpected interface.\n"); + IUnknown_Release(unknown); + + hr = IMoniker_QueryInterface(moniker, &CLSID_ObjrefMoniker, (void **)&unknown); + ok(unknown == (IUnknown *)moniker, "Unexpected interface.\n"); + IUnknown_Release(unknown); + + hr = IMoniker_QueryInterface(moniker, &IID_IMarshal, (void **)&marshal); + ok(hr == S_OK, "Failed to get interface, hr %#x.\n", hr); + + hr = IMarshal_GetUnmarshalClass(marshal, NULL, NULL, 0, NULL, 0, &clsid); + ok(hr == S_OK, "Failed to get class, hr %#x.\n", hr); + ok(IsEqualGUID(&clsid, &CLSID_ObjrefMoniker), "Unexpected class %s.\n", wine_dbgstr_guid(&clsid)); + + hr = IMarshal_GetMarshalSizeMax(marshal, &IID_IMoniker, NULL, CLSCTX_INPROC, NULL, 0, &size); + ok(hr == S_OK, "Failed to get marshal size, hr %#x.\n", hr); + ok(size > 0, "Unexpected size %d.\n", size); + + hr = CreateStreamOnHGlobal(NULL, TRUE, &stream); + ok(hr == S_OK, "Failed to create a stream, hr %#x.\n", hr); + + hr = CoMarshalInterface(stream, &IID_IMoniker, (IUnknown *)moniker, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL); + ok(hr == S_OK, "Failed to marshal moniker, hr %#x.\n", hr); + + pos.QuadPart = 0; + IStream_Seek(stream, pos, STREAM_SEEK_SET, NULL); + hr = CoUnmarshalInterface(stream, &IID_IMoniker, (void **)&moniker2); + ok(hr == S_OK, "Failed to unmarshal, hr %#x.\n", hr); + hr = IMoniker_IsEqual(moniker, moniker2); + ok(hr == S_OK, "Expected equal moniker, hr %#x.\n", hr); + IMoniker_Release(moniker2); + + IStream_Release(stream); + + IMarshal_Release(marshal); + + ok(factory.refcount > 1, "Unexpected factory refcount %u.\n", factory.refcount); + + /* Display Name */ + + hr = CreateBindCtx(0, &bindctx); + ok(hr == S_OK, "CreateBindCtx failed: 0x%08x\n", hr); + + hr = IMoniker_GetDisplayName(moniker, bindctx, NULL, &display_name); +todo_wine + ok(hr == S_OK, "IMoniker_GetDisplayName failed: 0x%08x\n", hr); + + IBindCtx_Release(bindctx); + + hr = IMoniker_IsDirty(moniker); + ok(hr == S_FALSE, "IMoniker_IsDirty should return S_FALSE, not 0x%08x\n", hr); + + /* IROTData::GetComparisonData test */ + + hr = IMoniker_QueryInterface(moniker, &IID_IROTData, (void **)&rotdata); + ok(hr == E_NOINTERFACE, "IMoniker_QueryInterface(IID_IROTData) should have returned E_NOINTERFACE instead of 0x%08x\n", hr); + + /* Saving */ + + hr = CreateStreamOnHGlobal(NULL, TRUE, &stream); + ok(hr == S_OK, "CreateStreamOnHGlobal failed: 0x%08x\n", hr); + + hr = IMoniker_Save(moniker, stream, TRUE); +todo_wine + ok(hr == S_OK, "IMoniker_Save failed: 0x%08x\n", hr); + + IStream_Release(stream); + + /* Hashing */ + hr = IMoniker_Hash(moniker, &hash); + ok(hr == S_OK, "IMoniker_Hash failed: 0x%08x\n", hr); + ok(hash == PtrToUlong(&factory.IClassFactory_iface), "Unexpected hash value %#x.\n", hash); + + /* IsSystemMoniker test */ + TEST_MONIKER_TYPE(moniker, MKSYS_OBJREFMONIKER); + + hr = IMoniker_Inverse(moniker, &inverse); + ok(hr == S_OK, "Failed to get inverse, hr %#x.\n", hr); + TEST_MONIKER_TYPE(inverse, MKSYS_ANTIMONIKER); + IMoniker_Release(inverse); + + hr = CreateBindCtx(0, &bindctx); + ok(hr == S_OK, "CreateBindCtx failed: 0x%08x\n", hr); + + /* IsRunning test */ + hr = IMoniker_IsRunning(moniker, bindctx, NULL, NULL); + ok(hr == S_OK, "IMoniker_IsRunning should return S_OK, not 0x%08x\n", hr); + + hr = IMoniker_GetTimeOfLastChange(moniker, bindctx, NULL, &filetime); + ok(hr == MK_E_UNAVAILABLE, "IMoniker_GetTimeOfLastChange should return MK_E_UNAVAILABLE, not 0x%08x\n", hr); + + hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown); + ok(hr == S_OK, "IMoniker_BindToObject failed: 0x%08x\n", hr); + IUnknown_Release(unknown); + + hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown); + ok(hr == S_OK, "IMoniker_BindToObject failed: 0x%08x\n", hr); + IUnknown_Release(unknown); + + IMoniker_Release(moniker); + + ok(factory.refcount == 1, "Unexpected factory refcount %u.\n", factory.refcount); + + hr = CreateObjrefMoniker(NULL, &moniker); + ok(hr == S_OK, "CreateObjrefMoniker failed, hr %#x.\n", hr); + + hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown); + ok(hr == E_UNEXPECTED, "IMoniker_BindToObject should have returned E_UNEXPECTED instead of 0x%08x\n", hr); + + hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown); + ok(hr == E_UNEXPECTED, "IMoniker_BindToStorage should have returned E_UNEXPECTED instead of 0x%08x\n", hr); + + IBindCtx_Release(bindctx); + + /* Enum() */ + enummoniker = (void *)0xdeadbeef; + hr = IMoniker_Enum(moniker, TRUE, &enummoniker); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(enummoniker == NULL, "got %p\n", enummoniker); + + enummoniker = (void *)0xdeadbeef; + hr = IMoniker_Enum(moniker, FALSE, &enummoniker); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(enummoniker == NULL, "got %p\n", enummoniker); + + IMoniker_Release(moniker); + + /* CommonPrefixWith() */ + hr = CreateObjrefMoniker((IUnknown *)&factory.IClassFactory_iface, &moniker); + ok(hr == S_OK, "CreateObjrefMoniker failed: hr %#x.\n", hr); + + hr = CreateObjrefMoniker((IUnknown *)&factory.IClassFactory_iface, &moniker2); + ok(hr == S_OK, "CreateObjrefMoniker failed: hr %#x.\n", hr); + + hr = IMoniker_IsEqual(moniker, NULL); + ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr); + + hr = IMoniker_IsEqual(moniker, moniker2); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + + hr = IMoniker_CommonPrefixWith(moniker, moniker2, NULL); + ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr); + + hr = IMoniker_CommonPrefixWith(moniker, NULL, &prefix); + ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr); + + hr = IMoniker_CommonPrefixWith(moniker, moniker2, &prefix); + ok(hr == MK_S_US, "Unexpected hr %#x.\n", hr); + ok(prefix == moniker, "Unexpected pointer.\n"); + IMoniker_Release(prefix); + + IMoniker_Release(moniker2); + + hr = CreateObjrefMoniker((IUnknown *)moniker, &moniker2); + ok(hr == S_OK, "Failed to create moniker, hr %#x.\n", hr); + + hr = IMoniker_IsEqual(moniker, moniker2); + ok(hr == S_FALSE, "Unexpected hr %#x.\n", hr); + + hr = IMoniker_CommonPrefixWith(moniker, moniker2, &prefix); + ok(hr == MK_E_NOPREFIX, "Unexpected hr %#x.\n", hr); + + IMoniker_Release(moniker2); + + /* ComposeWith() */ + + /* P + A -> () */ + anti = create_antimoniker(1); + hr = IMoniker_ComposeWith(moniker, anti, TRUE, &moniker2); + ok(hr == S_OK, "Failed to compose, hr %#x.\n", hr); + ok(!moniker2, "Unexpected pointer.\n"); + IMoniker_Release(anti); + + /* P + A2 -> A */ + anti = create_antimoniker(2); + hr = IMoniker_ComposeWith(moniker, anti, TRUE, &moniker2); + ok(hr == S_OK, "Failed to compose, hr %#x.\n", hr); + TEST_MONIKER_TYPE(moniker2, MKSYS_ANTIMONIKER); + IMoniker_Release(moniker2); + + IMoniker_Release(anti); + + IMoniker_Release(moniker); +} + static void test_bind_context(void) { IRunningObjectTable *rot, *rot2; @@ -4385,6 +4600,7 @@ START_TEST(moniker) test_anti_moniker(); test_generic_composite_moniker(); test_pointer_moniker(); + test_objref_moniker(); test_save_load_filemoniker(); test_MonikerCommonPrefixWith();
diff --git a/include/objidl.idl b/include/objidl.idl index 7576a686aeb..cd11729b292 100644 --- a/include/objidl.idl +++ b/include/objidl.idl @@ -330,7 +330,10 @@ interface IMoniker : IPersistStream MKSYS_ITEMMONIKER = 4, MKSYS_POINTERMONIKER = 5, /* MKSYS_URLMONIKER = 6, */ /* defined in urlmon.idl */ - MKSYS_CLASSMONIKER = 7 + MKSYS_CLASSMONIKER = 7, + MKSYS_OBJREFMONIKER = 8, + MKSYS_SESSIONMONIKER = 9, + MKSYS_LUAMONIKER = 10 } MKSYS;
typedef [v1_enum] enum tagMKREDUCE {
On 10/13/21 2:35 PM, Dmitry Timoshkov wrote:
+static const IMonikerVtbl VT_ObjrefMonikerImpl = +{
- ObjrefMonikerImpl_QueryInterface,
- PointerMonikerImpl_AddRef,
- PointerMonikerImpl_Release,
- ObjrefMonikerImpl_GetClassID,
- PointerMonikerImpl_IsDirty,
- PointerMonikerImpl_Load,
- ObjrefMonikerImpl_Save,
- PointerMonikerImpl_GetSizeMax,
- PointerMonikerImpl_BindToObject,
- PointerMonikerImpl_BindToStorage,
- PointerMonikerImpl_Reduce,
- PointerMonikerImpl_ComposeWith,
- ObjrefMonikerImpl_Enum,
- PointerMonikerImpl_IsEqual,
- PointerMonikerImpl_Hash,
- PointerMonikerImpl_IsRunning,
- ObjrefMonikerImpl_GetTimeOfLastChange,
- PointerMonikerImpl_Inverse,
- PointerMonikerImpl_CommonPrefixWith,
- PointerMonikerImpl_RelativePathTo,
- ObjrefMonikerImpl_GetDisplayName,
- PointerMonikerImpl_ParseDisplayName,
- ObjrefMonikerImpl_IsSystemMoniker
+};
I think separate implementation would be better. According to docs more methods are supposed to differ, like running state handling, or Load()/GetSizeMax().
It's worth checking if objref moniker keeps a reference to passed pointer at all. Since its purpose is to identify running object RPC-way, I suspect it's not a simple pointer wrapper.
+static PointerMonikerImpl *unsafe_impl_from_IMoniker(IMoniker *iface) +{
- if (iface->lpVtbl != &VT_PointerMonikerImpl && iface->lpVtbl != &VT_ObjrefMonikerImpl)
return NULL;
- return CONTAINING_RECORD(iface, PointerMonikerImpl, IMoniker_iface);
+}
This implies that IsEqual() could return S_OK for mismatching moniker types, which is not backed by tests, or docs.
There are some copy-paste problems in tests.
Nikolay Sivov nsivov@codeweavers.com wrote:
+static const IMonikerVtbl VT_ObjrefMonikerImpl = +{
- ObjrefMonikerImpl_QueryInterface,
- PointerMonikerImpl_AddRef,
- PointerMonikerImpl_Release,
- ObjrefMonikerImpl_GetClassID,
- PointerMonikerImpl_IsDirty,
- PointerMonikerImpl_Load,
- ObjrefMonikerImpl_Save,
- PointerMonikerImpl_GetSizeMax,
- PointerMonikerImpl_BindToObject,
- PointerMonikerImpl_BindToStorage,
- PointerMonikerImpl_Reduce,
- PointerMonikerImpl_ComposeWith,
- ObjrefMonikerImpl_Enum,
- PointerMonikerImpl_IsEqual,
- PointerMonikerImpl_Hash,
- PointerMonikerImpl_IsRunning,
- ObjrefMonikerImpl_GetTimeOfLastChange,
- PointerMonikerImpl_Inverse,
- PointerMonikerImpl_CommonPrefixWith,
- PointerMonikerImpl_RelativePathTo,
- ObjrefMonikerImpl_GetDisplayName,
- PointerMonikerImpl_ParseDisplayName,
- ObjrefMonikerImpl_IsSystemMoniker
+};
I think separate implementation would be better. According to docs more methods are supposed to differ, like running state handling, or Load()/GetSizeMax().
Initially I created a fully separate implementation, however after looking at the test results I moved to a less intrusive version. I think that once a method that differs in behaviour is found it's fairly easy to add another standalone implementation.
It's worth checking if objref moniker keeps a reference to passed pointer at all. Since its purpose is to identify running object RPC-way, I suspect it's not a simple pointer wrapper.
+static PointerMonikerImpl *unsafe_impl_from_IMoniker(IMoniker *iface) +{
- if (iface->lpVtbl != &VT_PointerMonikerImpl && iface->lpVtbl != &VT_ObjrefMonikerImpl)
return NULL;
- return CONTAINING_RECORD(iface, PointerMonikerImpl, IMoniker_iface);
+}
This implies that IsEqual() could return S_OK for mismatching moniker types, which is not backed by tests, or docs.
I guess that it could be a follow up patch. I should probably mention that this implementation works perfectly for a very large .Net based application.
On 10/13/21 3:13 PM, Dmitry Timoshkov wrote:
Nikolay Sivov nsivov@codeweavers.com wrote:
+static const IMonikerVtbl VT_ObjrefMonikerImpl = +{
- ObjrefMonikerImpl_QueryInterface,
- PointerMonikerImpl_AddRef,
- PointerMonikerImpl_Release,
- ObjrefMonikerImpl_GetClassID,
- PointerMonikerImpl_IsDirty,
- PointerMonikerImpl_Load,
- ObjrefMonikerImpl_Save,
- PointerMonikerImpl_GetSizeMax,
- PointerMonikerImpl_BindToObject,
- PointerMonikerImpl_BindToStorage,
- PointerMonikerImpl_Reduce,
- PointerMonikerImpl_ComposeWith,
- ObjrefMonikerImpl_Enum,
- PointerMonikerImpl_IsEqual,
- PointerMonikerImpl_Hash,
- PointerMonikerImpl_IsRunning,
- ObjrefMonikerImpl_GetTimeOfLastChange,
- PointerMonikerImpl_Inverse,
- PointerMonikerImpl_CommonPrefixWith,
- PointerMonikerImpl_RelativePathTo,
- ObjrefMonikerImpl_GetDisplayName,
- PointerMonikerImpl_ParseDisplayName,
- ObjrefMonikerImpl_IsSystemMoniker
+};
I think separate implementation would be better. According to docs more methods are supposed to differ, like running state handling, or Load()/GetSizeMax().
Initially I created a fully separate implementation, however after looking at the test results I moved to a less intrusive version. I think that once a method that differs in behaviour is found it's fairly easy to add another standalone implementation.
You already found that it differs, and at least methods mentioned above will differ as well.
With reused functions traces will be misleading as well.
It's worth checking if objref moniker keeps a reference to passed pointer at all. Since its purpose is to identify running object RPC-way, I suspect it's not a simple pointer wrapper.
+static PointerMonikerImpl *unsafe_impl_from_IMoniker(IMoniker *iface) +{
- if (iface->lpVtbl != &VT_PointerMonikerImpl && iface->lpVtbl != &VT_ObjrefMonikerImpl)
return NULL;
- return CONTAINING_RECORD(iface, PointerMonikerImpl, IMoniker_iface);
+}
This implies that IsEqual() could return S_OK for mismatching moniker types, which is not backed by tests, or docs.
I guess that it could be a follow up patch. I should probably mention that this implementation works perfectly for a very large .Net based application.
Like I said, it changes the way IsEqual() works.
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=99957
Your paranoid android.
=== w7u_2qxl (32 bit report) ===
ole32: moniker.c:4210: Test failed: Unexpected factory refcount 3.
=== w7u_adm (32 bit report) ===
ole32: moniker.c:4210: Test failed: Unexpected factory refcount 3.
=== w7u_el (32 bit report) ===
ole32: moniker.c:4210: Test failed: Unexpected factory refcount 3.
=== w8 (32 bit report) ===
ole32: moniker.c:4210: Test failed: Unexpected factory refcount 3.
=== w8adm (32 bit report) ===
ole32: moniker.c:4210: Test failed: Unexpected factory refcount 3.
=== w864 (32 bit report) ===
ole32: moniker.c:4210: Test failed: Unexpected factory refcount 3.
=== w1064v1507 (32 bit report) ===
ole32: moniker.c:4210: Test failed: Unexpected factory refcount 3.
=== w1064v1809 (32 bit report) ===
ole32: moniker.c:4210: Test failed: Unexpected factory refcount 3.
=== w1064 (32 bit report) ===
ole32: moniker.c:4210: Test failed: Unexpected factory refcount 3.
=== w1064_tsign (32 bit report) ===
ole32: moniker.c:4210: Test failed: Unexpected factory refcount 3.
=== w10pro64 (32 bit report) ===
ole32: moniker.c:4210: Test failed: Unexpected factory refcount 3.
=== w864 (64 bit report) ===
ole32: moniker.c:4210: Test failed: Unexpected factory refcount 3.
=== w1064v1507 (64 bit report) ===
ole32: moniker.c:4210: Test failed: Unexpected factory refcount 3.
=== w1064v1809 (64 bit report) ===
ole32: moniker.c:4210: Test failed: Unexpected factory refcount 3.
=== w1064 (64 bit report) ===
ole32: moniker.c:4210: Test failed: Unexpected factory refcount 3.
=== w1064_2qxl (64 bit report) ===
ole32: moniker.c:4210: Test failed: Unexpected factory refcount 3.
=== w1064_tsign (64 bit report) ===
ole32: moniker.c:4210: Test failed: Unexpected factory refcount 3.
=== w10pro64 (64 bit report) ===
ole32: moniker.c:4210: Test failed: Unexpected factory refcount 3.
=== w10pro64_ar (64 bit report) ===
ole32: moniker.c:4210: Test failed: Unexpected factory refcount 3.
=== w10pro64_he (64 bit report) ===
ole32: moniker.c:4210: Test failed: Unexpected factory refcount 3.
=== w10pro64_ja (64 bit report) ===
ole32: moniker.c:4210: Test failed: Unexpected factory refcount 3.
=== w10pro64_zh_CN (64 bit report) ===
ole32: moniker.c:4210: Test failed: Unexpected factory refcount 3.