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 {