[PATCH] ole32: Add CreateObjrefMoniker() stub implementation. (Resend).

Dmitry Timoshkov dmitry at baikal.ru
Mon Nov 22 01:48:29 CST 2021


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 | 418 +++++++++++++++++++++++++++++++++++-
 dlls/ole32/tests/moniker.c  | 249 ++++++++++++++++++++-
 include/objidl.idl          |   5 +-
 7 files changed, 691 insertions(+), 6 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..c95c835e9e3 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)
@@ -641,3 +641,419 @@ HRESULT WINAPI PointerMoniker_CreateInstance(IClassFactory *iface,
 
     return hr;
 }
+
+/* ObjrefMoniker implementation */
+
+typedef struct
+{
+    IMoniker IMoniker_iface;
+    IMarshal IMarshal_iface;
+
+    LONG refcount;
+
+    IUnknown *pObject;
+} ObjrefMonikerImpl;
+
+static inline ObjrefMonikerImpl *objref_impl_from_IMoniker(IMoniker *iface)
+{
+    return CONTAINING_RECORD(iface, ObjrefMonikerImpl, IMoniker_iface);
+}
+
+static ObjrefMonikerImpl *objref_impl_from_IMarshal(IMarshal *iface)
+{
+    return CONTAINING_RECORD(iface, ObjrefMonikerImpl, IMarshal_iface);
+}
+
+static HRESULT WINAPI ObjrefMonikerImpl_QueryInterface(IMoniker *iface, REFIID iid, void **obj)
+{
+    ObjrefMonikerImpl *moniker = objref_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 ULONG WINAPI ObjrefMonikerImpl_AddRef(IMoniker *iface)
+{
+    ObjrefMonikerImpl *moniker = objref_impl_from_IMoniker(iface);
+    ULONG refcount = InterlockedIncrement(&moniker->refcount);
+
+    TRACE("%p, refcount %u\n", iface, refcount);
+
+    return refcount;
+}
+
+static ULONG WINAPI ObjrefMonikerImpl_Release(IMoniker *iface)
+{
+    ObjrefMonikerImpl *moniker = objref_impl_from_IMoniker(iface);
+    ULONG refcount = InterlockedDecrement(&moniker->refcount);
+
+    TRACE("%p, refcount %u\n", iface, refcount);
+
+    if (!refcount)
+    {
+        if (moniker->pObject) IUnknown_Release(moniker->pObject);
+        heap_free(moniker);
+    }
+
+    return refcount;
+}
+
+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_IsDirty(IMoniker *iface)
+{
+    FIXME("(%p): stub\n", iface);
+    return S_FALSE;
+}
+
+static HRESULT WINAPI ObjrefMonikerImpl_Load(IMoniker *iface, IStream *stream)
+{
+    FIXME("(%p,%p): stub\n", iface, stream);
+    return E_NOTIMPL;
+}
+
+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_GetSizeMax(IMoniker *iface, ULARGE_INTEGER *size)
+{
+    FIXME("(%p,%p): stub\n", iface, size);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ObjrefMonikerImpl_BindToObject(IMoniker *iface, IBindCtx *pbc, IMoniker *left,
+        REFIID riid, void **result)
+{
+    FIXME("(%p,%p,%p,%s,%p): stub\n", iface, pbc, left, debugstr_guid(riid), result);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ObjrefMonikerImpl_BindToStorage(IMoniker *iface, IBindCtx *pbc, IMoniker *left,
+        REFIID riid, void **result)
+{
+    FIXME("(%p,%p,%p,%s,%p): stub\n", iface, pbc, left, debugstr_guid(riid), result);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ObjrefMonikerImpl_Reduce(IMoniker *iface, IBindCtx *pbc, DWORD howfar,
+        IMoniker **left, IMoniker **reduced)
+{
+    FIXME("(%p,%p,%d,%p,%p): stub\n", iface, pbc, howfar, left, reduced);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ObjrefMonikerImpl_ComposeWith(IMoniker *iface, IMoniker *right,
+        BOOL only_if_not_generic, IMoniker **result)
+{
+    FIXME("(%p,%p,%d,%p): stub\n", iface, right, only_if_not_generic, result);
+    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_IsEqual(IMoniker *iface, IMoniker *other)
+{
+    FIXME("(%p,%p): stub\n", iface, other);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ObjrefMonikerImpl_Hash(IMoniker *iface, DWORD *hash)
+{
+    ObjrefMonikerImpl *moniker = objref_impl_from_IMoniker(iface);
+
+    TRACE("(%p,%p)\n", iface, hash);
+
+    if (!hash)
+        return E_POINTER;
+
+    *hash = PtrToUlong(moniker->pObject);
+
+    return S_OK;
+}
+
+static HRESULT WINAPI ObjrefMonikerImpl_IsRunning(IMoniker *iface, IBindCtx *pbc, IMoniker *left,
+        IMoniker *running)
+{
+    FIXME("(%p,%p,%p,%p): stub\n", iface, pbc, left, running);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ObjrefMonikerImpl_GetTimeOfLastChange(IMoniker *iface,
+                               IBindCtx *pbc, IMoniker *left, FILETIME *time)
+{
+    FIXME("(%p,%p,%p,%p): stub\n", iface, pbc, left, time);
+    return MK_E_UNAVAILABLE;
+}
+
+static HRESULT WINAPI ObjrefMonikerImpl_Inverse(IMoniker *iface, IMoniker **moniker)
+{
+    FIXME("(%p,%p): stub\n", iface, moniker);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ObjrefMonikerImpl_CommonPrefixWith(IMoniker *iface, IMoniker *other, IMoniker **prefix)
+{
+    FIXME("(%p,%p,%p): stub\n", iface, other, prefix);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ObjrefMonikerImpl_RelativePathTo(IMoniker *iface, IMoniker *other, IMoniker **result)
+{
+    FIXME("(%p,%p,%p): stub\n", iface, other, result);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ObjrefMonikerImpl_GetDisplayName(IMoniker *iface, IBindCtx *pbc,
+                               IMoniker *left, LPOLESTR *name)
+{
+    FIXME("(%p,%p,%p,%p): stub\n", iface, pbc, left, name);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ObjrefMonikerImpl_ParseDisplayName(IMoniker *iface, IBindCtx *pbc,
+        IMoniker *left, LPOLESTR name, ULONG *eaten, IMoniker **out)
+{
+    FIXME("(%p,%p,%p,%p,%p,%p): stub\n", iface, pbc, left, name, eaten, out);
+    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,
+    ObjrefMonikerImpl_AddRef,
+    ObjrefMonikerImpl_Release,
+    ObjrefMonikerImpl_GetClassID,
+    ObjrefMonikerImpl_IsDirty,
+    ObjrefMonikerImpl_Load,
+    ObjrefMonikerImpl_Save,
+    ObjrefMonikerImpl_GetSizeMax,
+    ObjrefMonikerImpl_BindToObject,
+    ObjrefMonikerImpl_BindToStorage,
+    ObjrefMonikerImpl_Reduce,
+    ObjrefMonikerImpl_ComposeWith,
+    ObjrefMonikerImpl_Enum,
+    ObjrefMonikerImpl_IsEqual,
+    ObjrefMonikerImpl_Hash,
+    ObjrefMonikerImpl_IsRunning,
+    ObjrefMonikerImpl_GetTimeOfLastChange,
+    ObjrefMonikerImpl_Inverse,
+    ObjrefMonikerImpl_CommonPrefixWith,
+    ObjrefMonikerImpl_RelativePathTo,
+    ObjrefMonikerImpl_GetDisplayName,
+    ObjrefMonikerImpl_ParseDisplayName,
+    ObjrefMonikerImpl_IsSystemMoniker
+};
+
+static HRESULT WINAPI objref_moniker_marshal_QueryInterface(IMarshal *iface, REFIID riid, LPVOID *ppv)
+{
+    ObjrefMonikerImpl *moniker = objref_impl_from_IMarshal(iface);
+
+    TRACE("(%p,%s,%p)\n", iface, debugstr_guid(riid), ppv);
+
+    return IMoniker_QueryInterface(&moniker->IMoniker_iface, riid, ppv);
+}
+
+static ULONG WINAPI objref_moniker_marshal_AddRef(IMarshal *iface)
+{
+    ObjrefMonikerImpl *moniker = objref_impl_from_IMarshal(iface);
+
+    TRACE("(%p)\n", iface);
+
+    return IMoniker_AddRef(&moniker->IMoniker_iface);
+}
+
+static ULONG WINAPI objref_moniker_marshal_Release(IMarshal *iface)
+{
+    ObjrefMonikerImpl *moniker = objref_impl_from_IMarshal(iface);
+
+    TRACE("(%p)\n", iface);
+
+    return IMoniker_Release(&moniker->IMoniker_iface);
+}
+
+static HRESULT WINAPI objref_moniker_marshal_GetUnmarshalClass(IMarshal *iface, REFIID riid, void *pv,
+        DWORD dwDestContext, void *pvDestContext, DWORD mshlflags, CLSID *clsid)
+{
+    ObjrefMonikerImpl *moniker = objref_impl_from_IMarshal(iface);
+
+    TRACE("(%p,%s,%p,%08x,%p,%x,%p)\n", iface, debugstr_guid(riid), pv, dwDestContext, pvDestContext,
+            mshlflags, clsid);
+
+    return IMoniker_GetClassID(&moniker->IMoniker_iface, clsid);
+}
+
+static HRESULT WINAPI objref_moniker_marshal_GetMarshalSizeMax(IMarshal *iface, REFIID riid, void *pv,
+        DWORD dwDestContext, void *pvDestContext, DWORD mshlflags, DWORD *size)
+{
+    ObjrefMonikerImpl *moniker = objref_impl_from_IMarshal(iface);
+
+    TRACE("(%p,%s,%p,%08x,%p,%08x,%p)\n", iface, debugstr_guid(riid), pv, dwDestContext, pvDestContext,
+            mshlflags, size);
+
+    return CoGetMarshalSizeMax(size, &IID_IUnknown, moniker->pObject, dwDestContext, pvDestContext, mshlflags);
+}
+
+static HRESULT WINAPI objref_moniker_marshal_MarshalInterface(IMarshal *iface, IStream *stream, REFIID riid,
+        void *pv, DWORD dwDestContext, void *pvDestContext, DWORD mshlflags)
+{
+    ObjrefMonikerImpl *moniker = objref_impl_from_IMarshal(iface);
+
+    TRACE("(%p,%s,%p,%08x,%p,%08x)\n", stream, debugstr_guid(riid), pv, dwDestContext, pvDestContext, mshlflags);
+
+    return CoMarshalInterface(stream, &IID_IUnknown, moniker->pObject, dwDestContext, pvDestContext, mshlflags);
+}
+
+static HRESULT WINAPI objref_moniker_marshal_UnmarshalInterface(IMarshal *iface, IStream *stream,
+        REFIID riid, void **ppv)
+{
+    ObjrefMonikerImpl *moniker = objref_impl_from_IMarshal(iface);
+    IUnknown *object;
+    HRESULT hr;
+
+    TRACE("(%p,%p,%s,%p)\n", iface, stream, debugstr_guid(riid), ppv);
+
+    hr = CoUnmarshalInterface(stream, &IID_IUnknown, (void **)&object);
+    if (FAILED(hr))
+    {
+        ERR("Couldn't unmarshal moniker, hr = %#x.\n", hr);
+        return hr;
+    }
+
+    if (moniker->pObject)
+        IUnknown_Release(moniker->pObject);
+    moniker->pObject = object;
+
+    return IMoniker_QueryInterface(&moniker->IMoniker_iface, riid, ppv);
+}
+
+static HRESULT WINAPI objref_moniker_marshal_ReleaseMarshalData(IMarshal *iface, IStream *stream)
+{
+    TRACE("(%p,%p)\n", iface, stream);
+    return S_OK;
+}
+
+static HRESULT WINAPI objref_moniker_marshal_DisconnectObject(IMarshal *iface, DWORD reserved)
+{
+    TRACE("(%p,%08x)\n", iface, reserved);
+    return S_OK;
+}
+
+static const IMarshalVtbl objref_moniker_marshal_vtbl =
+{
+    objref_moniker_marshal_QueryInterface,
+    objref_moniker_marshal_AddRef,
+    objref_moniker_marshal_Release,
+    objref_moniker_marshal_GetUnmarshalClass,
+    objref_moniker_marshal_GetMarshalSizeMax,
+    objref_moniker_marshal_MarshalInterface,
+    objref_moniker_marshal_UnmarshalInterface,
+    objref_moniker_marshal_ReleaseMarshalData,
+    objref_moniker_marshal_DisconnectObject
+};
+
+/***********************************************************************
+ *           CreateObjrefMoniker (OLE32.@)
+ */
+HRESULT WINAPI CreateObjrefMoniker(IUnknown *obj, IMoniker **ret)
+{
+    ObjrefMonikerImpl *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 = &objref_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..d2c83c173ba 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,249 @@ 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, "Unexpected hr %#x\n", hr);
+
+    hr = CreateObjrefMoniker((IUnknown *)&factory.IClassFactory_iface, &moniker);
+    ok(hr == S_OK, "Unexpected 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);
+todo_wine
+    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);
+todo_wine
+    ok(hr == S_OK, "Failed to get inverse, hr %#x\n", hr);
+if (hr == S_OK)
+{
+    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);
+todo_wine
+    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);
+todo_wine
+    ok(hr == S_OK, "IMoniker_BindToObject failed: 0x%08x\n", hr);
+if (hr == S_OK)
+    IUnknown_Release(unknown);
+
+    hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
+todo_wine
+    ok(hr == S_OK, "IMoniker_BindToObject failed: 0x%08x\n", hr);
+if (hr == S_OK)
+    IUnknown_Release(unknown);
+
+    IMoniker_Release(moniker);
+
+todo_wine
+    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);
+todo_wine
+    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);
+todo_wine
+    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);
+todo_wine
+    ok(hr == E_INVALIDARG, "Unexpected hr %#x\n", hr);
+
+    hr = IMoniker_IsEqual(moniker, moniker2);
+todo_wine
+    ok(hr == S_OK, "Unexpected hr %#x\n", hr);
+
+    hr = IMoniker_CommonPrefixWith(moniker, moniker2, NULL);
+todo_wine
+    ok(hr == E_INVALIDARG, "Unexpected hr %#x\n", hr);
+
+    hr = IMoniker_CommonPrefixWith(moniker, NULL, &prefix);
+todo_wine
+    ok(hr == E_INVALIDARG, "Unexpected hr %#x\n", hr);
+
+    hr = IMoniker_CommonPrefixWith(moniker, moniker2, &prefix);
+todo_wine
+    ok(hr == MK_S_US, "Unexpected hr %#x\n", hr);
+if (hr == S_OK)
+{
+    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);
+todo_wine
+    ok(hr == S_FALSE, "Unexpected hr %#x\n", hr);
+
+    hr = IMoniker_CommonPrefixWith(moniker, moniker2, &prefix);
+todo_wine
+    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);
+todo_wine
+    ok(hr == S_OK, "Failed to compose, hr %#x\n", hr);
+if (hr == S_OK)
+    ok(!moniker2, "Unexpected pointer\n");
+    IMoniker_Release(anti);
+
+    /* P + A2 -> A */
+    anti = create_antimoniker(2);
+    hr = IMoniker_ComposeWith(moniker, anti, TRUE, &moniker2);
+todo_wine
+    ok(hr == S_OK, "Failed to compose, hr %#x\n", hr);
+if (hr == S_OK)
+{
+    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 +4629,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