ole32: Implement custom marshalling for pointer monikers.

Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Nikolay Sivov 2020-01-29 16:57:00 +03:00 committed by Alexandre Julliard
parent ef889fe654
commit a3909647b2
2 changed files with 160 additions and 7 deletions

View File

@ -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);

View File

@ -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);