[PATCH] ole32: Implement CreateObjrefMoniker().

Dmitry Timoshkov dmitry at baikal.ru
Wed Oct 13 06:35:48 CDT 2021


test_objref_moniker() is a copy of test_pointer_moniker() with appropriate changes.

Signed-off-by: Dmitry Timoshkov <dmitry at 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 {
-- 
2.31.1




More information about the wine-devel mailing list