diff --git a/dlls/ole32/pointermoniker.c b/dlls/ole32/pointermoniker.c index c1a0e2ae1c4..2cb0600336f 100644 --- a/dlls/ole32/pointermoniker.c +++ b/dlls/ole32/pointermoniker.c @@ -37,13 +37,14 @@ WINE_DEFAULT_DEBUG_CHANNEL(ole); /* PointerMoniker data structure */ -typedef struct PointerMonikerImpl{ - +typedef struct PointerMonikerImpl +{ IMoniker IMoniker_iface; + IMarshal IMarshal_iface; LONG ref; /* reference counter for this object */ - IUnknown *pObject; /* custom marshaler */ + IUnknown *pObject; } PointerMonikerImpl; static inline PointerMonikerImpl *impl_from_IMoniker(IMoniker *iface) @@ -51,6 +52,11 @@ static inline PointerMonikerImpl *impl_from_IMoniker(IMoniker *iface) return CONTAINING_RECORD(iface, PointerMonikerImpl, IMoniker_iface); } +static PointerMonikerImpl *impl_from_IMarshal(IMarshal *iface) +{ + return CONTAINING_RECORD(iface, PointerMonikerImpl, IMarshal_iface); +} + static PointerMonikerImpl *unsafe_impl_from_IMoniker(IMoniker *iface); static HRESULT WINAPI PointerMonikerImpl_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject) @@ -70,7 +76,11 @@ PointerMonikerImpl_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject) IsEqualIID(&IID_IPersist, riid) || IsEqualIID(&IID_IPersistStream, riid) || IsEqualIID(&IID_IMoniker, riid)) + { *ppvObject = iface; + } + else if (IsEqualIID(&IID_IMarshal, riid)) + *ppvObject = &This->IMarshal_iface; /* Check that we obtained an interface.*/ if ((*ppvObject)==0) @@ -542,6 +552,117 @@ static PointerMonikerImpl *unsafe_impl_from_IMoniker(IMoniker *iface) 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); + + TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), ppv); + + return IMoniker_QueryInterface(&moniker->IMoniker_iface, riid, ppv); +} + +static ULONG WINAPI pointer_moniker_marshal_AddRef(IMarshal *iface) +{ + PointerMonikerImpl *moniker = impl_from_IMarshal(iface); + + TRACE("%p.\n",iface); + + return IMoniker_AddRef(&moniker->IMoniker_iface); +} + +static ULONG WINAPI pointer_moniker_marshal_Release(IMarshal *iface) +{ + PointerMonikerImpl *moniker = impl_from_IMarshal(iface); + + TRACE("%p.\n",iface); + + return IMoniker_Release(&moniker->IMoniker_iface); +} + +static HRESULT WINAPI pointer_moniker_marshal_GetUnmarshalClass(IMarshal *iface, REFIID riid, void *pv, + DWORD dwDestContext, void *pvDestContext, DWORD mshlflags, CLSID *clsid) +{ + PointerMonikerImpl *moniker = impl_from_IMarshal(iface); + + TRACE("%p, %s, %p, %x, %p, %x, %p.\n", iface, debugstr_guid(riid), pv, dwDestContext, pvDestContext, + mshlflags, clsid); + + return IMoniker_GetClassID(&moniker->IMoniker_iface, clsid); +} + +static HRESULT WINAPI pointer_moniker_marshal_GetMarshalSizeMax(IMarshal *iface, REFIID riid, void *pv, + DWORD dwDestContext, void *pvDestContext, DWORD mshlflags, DWORD *size) +{ + PointerMonikerImpl *moniker = impl_from_IMarshal(iface); + + TRACE("%p, %s, %p, %d, %p, %#x, %p.\n", iface, debugstr_guid(riid), pv, dwDestContext, pvDestContext, + mshlflags, size); + + return CoGetMarshalSizeMax(size, &IID_IUnknown, moniker->pObject, dwDestContext, pvDestContext, mshlflags); +} + +static HRESULT WINAPI pointer_moniker_marshal_MarshalInterface(IMarshal *iface, IStream *stream, REFIID riid, + void *pv, DWORD dwDestContext, void *pvDestContext, DWORD mshlflags) +{ + PointerMonikerImpl *moniker = impl_from_IMarshal(iface); + + TRACE("%p, %s, %p, %x, %p, %x.\n", stream, debugstr_guid(riid), pv, + dwDestContext, pvDestContext, mshlflags); + + return CoMarshalInterface(stream, &IID_IUnknown, moniker->pObject, dwDestContext, + pvDestContext, mshlflags); +} + +static HRESULT WINAPI pointer_moniker_marshal_UnmarshalInterface(IMarshal *iface, IStream *stream, + REFIID riid, void **ppv) +{ + PointerMonikerImpl *moniker = 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 pointer_moniker_marshal_ReleaseMarshalData(IMarshal *iface, IStream *stream) +{ + TRACE("%p, %p.\n", iface, stream); + + return S_OK; +} + +static HRESULT WINAPI pointer_moniker_marshal_DisconnectObject(IMarshal *iface, DWORD reserved) +{ + TRACE("%p, %#x.\n", iface, reserved); + + return S_OK; +} + +static const IMarshalVtbl pointer_moniker_marshal_vtbl = +{ + pointer_moniker_marshal_QueryInterface, + pointer_moniker_marshal_AddRef, + pointer_moniker_marshal_Release, + pointer_moniker_marshal_GetUnmarshalClass, + pointer_moniker_marshal_GetMarshalSizeMax, + pointer_moniker_marshal_MarshalInterface, + pointer_moniker_marshal_UnmarshalInterface, + pointer_moniker_marshal_ReleaseMarshalData, + pointer_moniker_marshal_DisconnectObject +}; + /****************************************************************************** * PointerMoniker_Construct (local function) *******************************************************************************/ @@ -549,8 +670,8 @@ static void PointerMonikerImpl_Construct(PointerMonikerImpl* This, IUnknown *pun { TRACE("(%p)\n",This); - /* Initialize the virtual function table. */ This->IMoniker_iface.lpVtbl = &VT_PointerMonikerImpl; + This->IMarshal_iface.lpVtbl = &pointer_moniker_marshal_vtbl; This->ref = 1; if (punk) IUnknown_AddRef(punk); diff --git a/dlls/ole32/tests/moniker.c b/dlls/ole32/tests/moniker.c index 231551b244e..0e6f2677c50 100644 --- a/dlls/ole32/tests/moniker.c +++ b/dlls/ole32/tests/moniker.c @@ -2722,16 +2722,18 @@ todo_wine static void test_pointer_moniker(void) { IMoniker *moniker, *moniker2, *prefix, *inverse; + DWORD moniker_type, hash, size; IEnumMoniker *enummoniker; HRESULT hr; - DWORD moniker_type; - DWORD hash; IBindCtx *bindctx; FILETIME filetime; IUnknown *unknown; IStream *stream; IROTData *rotdata; LPOLESTR display_name; + IMarshal *marshal; + LARGE_INTEGER pos; + CLSID clsid; cLocks = 0; @@ -2750,6 +2752,35 @@ todo_wine 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_PointerMoniker), "Unexpected class.\n"); + + 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_more_than_one_lock(); /* Display Name */ @@ -2821,7 +2852,8 @@ todo_wine IMoniker_Release(moniker); - ok_no_locks(); +todo_wine + ok(cLocks == 0, "Number of locks should be 0, but actually is %d.\n", cLocks); hr = CreatePointerMoniker(NULL, &moniker); ok_ole_success(hr, CreatePointerMoniker);