Signed-off-by: Dmitry Timoshkov <dmitry(a)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