combase: Move CoCreateFreeThreadedMarshaler().

Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com>
Signed-off-by: Huw Davies <huw@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Nikolay Sivov 2020-08-12 11:12:29 +03:00 committed by Alexandre Julliard
parent 0bcbc4693e
commit 3a413b91b9
4 changed files with 297 additions and 314 deletions

View File

@ -77,7 +77,7 @@
@ stub CoCancelCall
@ stdcall CoCopyProxy(ptr ptr)
@ stdcall CoCreateErrorInfo(ptr) CreateErrorInfo
@ stdcall CoCreateFreeThreadedMarshaler(ptr ptr) ole32.CoCreateFreeThreadedMarshaler
@ stdcall CoCreateFreeThreadedMarshaler(ptr ptr)
@ stdcall CoCreateGuid(ptr)
@ stdcall CoCreateInstance(ptr ptr long ptr ptr)
@ stdcall CoCreateInstanceEx(ptr ptr long ptr long ptr) ole32.CoCreateInstanceEx

View File

@ -1,4 +1,5 @@
/*
* Copyright 2002 Juergen Schmied
* Copyright 2002 Marcus Meissner
* Copyright 2004 Mike Hearn, for CodeWeavers
* Copyright 2004 Rob Shearman, for CodeWeavers
@ -22,9 +23,28 @@
#include "objbase.h"
#include "wine/debug.h"
#include "wine/heap.h"
WINE_DEFAULT_DEBUG_CHANNEL(ole);
struct ftmarshaler
{
IUnknown IUnknown_inner;
IMarshal IMarshal_iface;
IUnknown *outer_unk;
LONG refcount;
};
static struct ftmarshaler *impl_ft_from_IUnknown(IUnknown *iface)
{
return CONTAINING_RECORD(iface, struct ftmarshaler, IUnknown_inner);
}
static struct ftmarshaler *impl_ft_from_IMarshal(IMarshal *iface)
{
return CONTAINING_RECORD(iface, struct ftmarshaler, IMarshal_iface);
}
/***********************************************************************
* CoMarshalHresult (combase.@)
*/
@ -84,3 +104,278 @@ HRESULT WINAPI CoMarshalInterThreadInterfaceInStream(REFIID riid, IUnknown *unk,
return hr;
}
static HRESULT WINAPI ftmarshaler_inner_QueryInterface(IUnknown *iface, REFIID riid, void **obj)
{
struct ftmarshaler *marshaler = impl_ft_from_IUnknown(iface);
TRACE("%p, %s, %p\n", iface, debugstr_guid(riid), obj);
*obj = NULL;
if (IsEqualIID(&IID_IUnknown, riid))
*obj = &marshaler->IUnknown_inner;
else if (IsEqualIID(&IID_IMarshal, riid))
*obj = &marshaler->IMarshal_iface;
else
{
FIXME("No interface for %s\n", debugstr_guid(riid));
return E_NOINTERFACE;
}
IUnknown_AddRef((IUnknown *)*obj);
return S_OK;
}
static ULONG WINAPI ftmarshaler_inner_AddRef(IUnknown *iface)
{
struct ftmarshaler *marshaler = impl_ft_from_IUnknown(iface);
ULONG refcount = InterlockedIncrement(&marshaler->refcount);
TRACE("%p, refcount %u\n", iface, refcount);
return refcount;
}
static ULONG WINAPI ftmarshaler_inner_Release(IUnknown *iface)
{
struct ftmarshaler *marshaler = impl_ft_from_IUnknown(iface);
ULONG refcount = InterlockedDecrement(&marshaler->refcount);
TRACE("%p, refcount %u\n", iface, refcount);
if (!refcount)
heap_free(marshaler);
return refcount;
}
static const IUnknownVtbl ftmarshaler_inner_vtbl =
{
ftmarshaler_inner_QueryInterface,
ftmarshaler_inner_AddRef,
ftmarshaler_inner_Release
};
static HRESULT WINAPI ftmarshaler_QueryInterface(IMarshal *iface, REFIID riid, void **obj)
{
struct ftmarshaler *marshaler = impl_ft_from_IMarshal(iface);
TRACE("%p, %s, %p\n", iface, debugstr_guid(riid), obj);
return IUnknown_QueryInterface(marshaler->outer_unk, riid, obj);
}
static ULONG WINAPI ftmarshaler_AddRef(IMarshal *iface)
{
struct ftmarshaler *marshaler = impl_ft_from_IMarshal(iface);
TRACE("%p\n", iface);
return IUnknown_AddRef(marshaler->outer_unk);
}
static ULONG WINAPI ftmarshaler_Release(IMarshal *iface)
{
struct ftmarshaler *marshaler = impl_ft_from_IMarshal(iface);
TRACE("%p\n", iface);
return IUnknown_Release(marshaler->outer_unk);
}
static HRESULT WINAPI ftmarshaler_GetUnmarshalClass(IMarshal *iface, REFIID riid, void *pv,
DWORD dest_context, void *pvDestContext, DWORD mshlflags, CLSID *clsid)
{
TRACE("%s, %p, %#x, %p, %#x, %p\n", debugstr_guid(riid), pv, dest_context, pvDestContext, mshlflags, clsid);
if (dest_context == MSHCTX_INPROC || dest_context == MSHCTX_CROSSCTX)
*clsid = CLSID_InProcFreeMarshaler;
else
*clsid = CLSID_StdMarshal;
return S_OK;
}
static HRESULT WINAPI ftmarshaler_GetMarshalSizeMax(IMarshal *iface, REFIID riid, void *pv,
DWORD dest_context, void *pvDestContext, DWORD mshlflags, DWORD *size)
{
IMarshal *marshal = NULL;
HRESULT hr;
TRACE("%s, %p, %#x, %p, %#x, %p\n", debugstr_guid(riid), pv, dest_context, pvDestContext, mshlflags, size);
/* If the marshalling happens inside the same process the interface pointer is
copied between the apartments */
if (dest_context == MSHCTX_INPROC || dest_context == MSHCTX_CROSSCTX)
{
*size = sizeof(mshlflags) + sizeof(pv) + sizeof(DWORD) + sizeof(GUID);
return S_OK;
}
/* Use the standard marshaller to handle all other cases */
CoGetStandardMarshal(riid, pv, dest_context, pvDestContext, mshlflags, &marshal);
hr = IMarshal_GetMarshalSizeMax(marshal, riid, pv, dest_context, pvDestContext, mshlflags, size);
IMarshal_Release(marshal);
return hr;
}
static HRESULT WINAPI ftmarshaler_MarshalInterface(IMarshal *iface, IStream *stream, REFIID riid,
void *pv, DWORD dest_context, void *pvDestContext, DWORD mshlflags)
{
IMarshal *marshal = NULL;
HRESULT hr;
TRACE("%p, %s, %p, %#x, %p, %#x\n", stream, debugstr_guid(riid), pv,
dest_context, pvDestContext, mshlflags);
/* If the marshalling happens inside the same process the interface pointer is
copied between the apartments */
if (dest_context == MSHCTX_INPROC || dest_context == MSHCTX_CROSSCTX)
{
void *object;
DWORD constant = 0;
GUID unknown_guid = { 0 };
hr = IUnknown_QueryInterface((IUnknown *)pv, riid, &object);
if (FAILED(hr))
return hr;
/* don't hold a reference to table-weak marshaled interfaces */
if (mshlflags & MSHLFLAGS_TABLEWEAK)
IUnknown_Release((IUnknown *)object);
hr = IStream_Write(stream, &mshlflags, sizeof(mshlflags), NULL);
if (hr != S_OK) return STG_E_MEDIUMFULL;
hr = IStream_Write(stream, &object, sizeof(object), NULL);
if (hr != S_OK) return STG_E_MEDIUMFULL;
if (sizeof(object) == sizeof(DWORD))
{
hr = IStream_Write(stream, &constant, sizeof(constant), NULL);
if (hr != S_OK) return STG_E_MEDIUMFULL;
}
hr = IStream_Write(stream, &unknown_guid, sizeof(unknown_guid), NULL);
if (hr != S_OK) return STG_E_MEDIUMFULL;
return S_OK;
}
/* Use the standard marshaler to handle all other cases */
CoGetStandardMarshal(riid, pv, dest_context, pvDestContext, mshlflags, &marshal);
hr = IMarshal_MarshalInterface(marshal, stream, riid, pv, dest_context, pvDestContext, mshlflags);
IMarshal_Release(marshal);
return hr;
}
static HRESULT WINAPI ftmarshaler_UnmarshalInterface(IMarshal *iface, IStream *stream, REFIID riid, void **ppv)
{
DWORD mshlflags;
IUnknown *object;
DWORD constant;
GUID unknown_guid;
HRESULT hr;
TRACE("%p, %s, %p\n", stream, debugstr_guid(riid), ppv);
hr = IStream_Read(stream, &mshlflags, sizeof(mshlflags), NULL);
if (hr != S_OK) return STG_E_READFAULT;
hr = IStream_Read(stream, &object, sizeof(object), NULL);
if (hr != S_OK) return STG_E_READFAULT;
if (sizeof(object) == sizeof(DWORD))
{
hr = IStream_Read(stream, &constant, sizeof(constant), NULL);
if (hr != S_OK) return STG_E_READFAULT;
if (constant != 0)
FIXME("constant is 0x%x instead of 0\n", constant);
}
hr = IStream_Read(stream, &unknown_guid, sizeof(unknown_guid), NULL);
if (hr != S_OK) return STG_E_READFAULT;
hr = IUnknown_QueryInterface(object, riid, ppv);
if (!(mshlflags & (MSHLFLAGS_TABLEWEAK | MSHLFLAGS_TABLESTRONG)))
IUnknown_Release(object);
return hr;
}
static HRESULT WINAPI ftmarshaler_ReleaseMarshalData(IMarshal *iface, IStream *stream)
{
DWORD mshlflags;
IUnknown *object;
DWORD constant;
GUID unknown_guid;
HRESULT hr;
TRACE("%p\n", stream);
hr = IStream_Read(stream, &mshlflags, sizeof(mshlflags), NULL);
if (hr != S_OK) return STG_E_READFAULT;
hr = IStream_Read(stream, &object, sizeof(object), NULL);
if (hr != S_OK) return STG_E_READFAULT;
if (sizeof(object) == sizeof(DWORD))
{
hr = IStream_Read(stream, &constant, sizeof(constant), NULL);
if (hr != S_OK) return STG_E_READFAULT;
if (constant != 0)
FIXME("constant is 0x%x instead of 0\n", constant);
}
hr = IStream_Read(stream, &unknown_guid, sizeof(unknown_guid), NULL);
if (hr != S_OK) return STG_E_READFAULT;
IUnknown_Release(object);
return S_OK;
}
static HRESULT WINAPI ftmarshaler_DisconnectObject(IMarshal *iface, DWORD reserved)
{
TRACE("\n");
/* nothing to do */
return S_OK;
}
static const IMarshalVtbl ftmarshaler_vtbl =
{
ftmarshaler_QueryInterface,
ftmarshaler_AddRef,
ftmarshaler_Release,
ftmarshaler_GetUnmarshalClass,
ftmarshaler_GetMarshalSizeMax,
ftmarshaler_MarshalInterface,
ftmarshaler_UnmarshalInterface,
ftmarshaler_ReleaseMarshalData,
ftmarshaler_DisconnectObject
};
/***********************************************************************
* CoCreateFreeThreadedMarshaler (combase.@)
*/
HRESULT WINAPI CoCreateFreeThreadedMarshaler(IUnknown *outer, IUnknown **marshaler)
{
struct ftmarshaler *object;
TRACE("%p, %p\n", outer, marshaler);
object = heap_alloc(sizeof(*object));
if (!object)
return E_OUTOFMEMORY;
object->IUnknown_inner.lpVtbl = &ftmarshaler_inner_vtbl;
object->IMarshal_iface.lpVtbl = &ftmarshaler_vtbl;
object->refcount = 1;
object->outer_unk = outer ? outer : &object->IUnknown_inner;
*marshaler = &object->IUnknown_inner;
return S_OK;
}

View File

@ -36,318 +36,6 @@
WINE_DEFAULT_DEBUG_CHANNEL(ole);
typedef struct _FTMarshalImpl {
IUnknown IUnknown_inner;
IMarshal IMarshal_iface;
IUnknown *outer_unk;
LONG ref;
} FTMarshalImpl;
static inline FTMarshalImpl *impl_from_IUnknown(IUnknown *iface)
{
return CONTAINING_RECORD(iface, FTMarshalImpl, IUnknown_inner);
}
static inline FTMarshalImpl *impl_from_IMarshal( IMarshal *iface )
{
return CONTAINING_RECORD(iface, FTMarshalImpl, IMarshal_iface);
}
/* inner IUnknown to handle aggregation */
static HRESULT WINAPI
IiFTMUnknown_fnQueryInterface (IUnknown * iface, REFIID riid, LPVOID * ppv)
{
FTMarshalImpl *This = impl_from_IUnknown(iface);
TRACE ("\n");
*ppv = NULL;
if (IsEqualIID (&IID_IUnknown, riid))
*ppv = &This->IUnknown_inner;
else if (IsEqualIID (&IID_IMarshal, riid))
*ppv = &This->IMarshal_iface;
else {
FIXME ("No interface for %s.\n", debugstr_guid (riid));
return E_NOINTERFACE;
}
IUnknown_AddRef ((IUnknown *) * ppv);
return S_OK;
}
static ULONG WINAPI IiFTMUnknown_fnAddRef (IUnknown * iface)
{
FTMarshalImpl *This = impl_from_IUnknown(iface);
TRACE ("\n");
return InterlockedIncrement (&This->ref);
}
static ULONG WINAPI IiFTMUnknown_fnRelease (IUnknown * iface)
{
FTMarshalImpl *This = impl_from_IUnknown(iface);
TRACE ("\n");
if (InterlockedDecrement (&This->ref))
return This->ref;
HeapFree (GetProcessHeap (), 0, This);
return 0;
}
static const IUnknownVtbl iunkvt =
{
IiFTMUnknown_fnQueryInterface,
IiFTMUnknown_fnAddRef,
IiFTMUnknown_fnRelease
};
static HRESULT WINAPI
FTMarshalImpl_QueryInterface (LPMARSHAL iface, REFIID riid, LPVOID * ppv)
{
FTMarshalImpl *This = impl_from_IMarshal(iface);
TRACE ("(%p)->(%s,%p)\n", This, debugstr_guid (riid), ppv);
return IUnknown_QueryInterface(This->outer_unk, riid, ppv);
}
static ULONG WINAPI
FTMarshalImpl_AddRef (LPMARSHAL iface)
{
FTMarshalImpl *This = impl_from_IMarshal(iface);
TRACE ("\n");
return IUnknown_AddRef(This->outer_unk);
}
static ULONG WINAPI
FTMarshalImpl_Release (LPMARSHAL iface)
{
FTMarshalImpl *This = impl_from_IMarshal(iface);
TRACE ("\n");
return IUnknown_Release(This->outer_unk);
}
static HRESULT WINAPI
FTMarshalImpl_GetUnmarshalClass (LPMARSHAL iface, REFIID riid, void *pv, DWORD dwDestContext,
void *pvDestContext, DWORD mshlflags, CLSID * pCid)
{
TRACE("(%s, %p, 0x%x, %p, 0x%x, %p)\n", debugstr_guid(riid), pv,
dwDestContext, pvDestContext, mshlflags, pCid);
if (dwDestContext == MSHCTX_INPROC || dwDestContext == MSHCTX_CROSSCTX)
*pCid = CLSID_InProcFreeMarshaler;
else
*pCid = CLSID_StdMarshal;
return S_OK;
}
static HRESULT WINAPI
FTMarshalImpl_GetMarshalSizeMax (LPMARSHAL iface, REFIID riid, void *pv, DWORD dwDestContext,
void *pvDestContext, DWORD mshlflags, DWORD * pSize)
{
IMarshal *pMarshal = NULL;
HRESULT hres;
TRACE("(%s, %p, 0x%x, %p, 0x%x, %p)\n", debugstr_guid(riid), pv,
dwDestContext, pvDestContext, mshlflags, pSize);
/* if the marshalling happens inside the same process the interface pointer is
copied between the apartments */
if (dwDestContext == MSHCTX_INPROC || dwDestContext == MSHCTX_CROSSCTX) {
*pSize = sizeof (mshlflags) + sizeof (pv) + sizeof (DWORD) + sizeof (GUID);
return S_OK;
}
/* use the standard marshaller to handle all other cases */
CoGetStandardMarshal (riid, pv, dwDestContext, pvDestContext, mshlflags, &pMarshal);
hres = IMarshal_GetMarshalSizeMax (pMarshal, riid, pv, dwDestContext, pvDestContext, mshlflags, pSize);
IMarshal_Release (pMarshal);
return hres;
}
static HRESULT WINAPI
FTMarshalImpl_MarshalInterface (LPMARSHAL iface, IStream * pStm, REFIID riid, void *pv,
DWORD dwDestContext, void *pvDestContext, DWORD mshlflags)
{
IMarshal *pMarshal = NULL;
HRESULT hres;
TRACE("(%p, %s, %p, 0x%x, %p, 0x%x)\n", pStm, debugstr_guid(riid), pv,
dwDestContext, pvDestContext, mshlflags);
/* if the marshalling happens inside the same process the interface pointer is
copied between the apartments */
if (dwDestContext == MSHCTX_INPROC || dwDestContext == MSHCTX_CROSSCTX) {
void *object;
DWORD constant = 0;
GUID unknown_guid = { 0 };
hres = IUnknown_QueryInterface((IUnknown *)pv, riid, &object);
if (FAILED(hres))
return hres;
/* don't hold a reference to table-weak marshaled interfaces */
if (mshlflags & MSHLFLAGS_TABLEWEAK)
IUnknown_Release((IUnknown *)object);
hres = IStream_Write (pStm, &mshlflags, sizeof (mshlflags), NULL);
if (hres != S_OK) return STG_E_MEDIUMFULL;
hres = IStream_Write (pStm, &object, sizeof (object), NULL);
if (hres != S_OK) return STG_E_MEDIUMFULL;
if (sizeof(object) == sizeof(DWORD))
{
hres = IStream_Write (pStm, &constant, sizeof (constant), NULL);
if (hres != S_OK) return STG_E_MEDIUMFULL;
}
hres = IStream_Write (pStm, &unknown_guid, sizeof (unknown_guid), NULL);
if (hres != S_OK) return STG_E_MEDIUMFULL;
return S_OK;
}
/* use the standard marshaler to handle all other cases */
CoGetStandardMarshal (riid, pv, dwDestContext, pvDestContext, mshlflags, &pMarshal);
hres = IMarshal_MarshalInterface (pMarshal, pStm, riid, pv, dwDestContext, pvDestContext, mshlflags);
IMarshal_Release (pMarshal);
return hres;
}
static HRESULT WINAPI
FTMarshalImpl_UnmarshalInterface (LPMARSHAL iface, IStream * pStm, REFIID riid, void **ppv)
{
DWORD mshlflags;
IUnknown *object;
DWORD constant;
GUID unknown_guid;
HRESULT hres;
TRACE ("(%p, %s, %p)\n", pStm, debugstr_guid(riid), ppv);
hres = IStream_Read (pStm, &mshlflags, sizeof (mshlflags), NULL);
if (hres != S_OK) return STG_E_READFAULT;
hres = IStream_Read (pStm, &object, sizeof (object), NULL);
if (hres != S_OK) return STG_E_READFAULT;
if (sizeof(object) == sizeof(DWORD))
{
hres = IStream_Read (pStm, &constant, sizeof (constant), NULL);
if (hres != S_OK) return STG_E_READFAULT;
if (constant != 0)
FIXME("constant is 0x%x instead of 0\n", constant);
}
hres = IStream_Read (pStm, &unknown_guid, sizeof (unknown_guid), NULL);
if (hres != S_OK) return STG_E_READFAULT;
hres = IUnknown_QueryInterface(object, riid, ppv);
if (!(mshlflags & (MSHLFLAGS_TABLEWEAK|MSHLFLAGS_TABLESTRONG)))
IUnknown_Release(object);
return hres;
}
static HRESULT WINAPI FTMarshalImpl_ReleaseMarshalData (LPMARSHAL iface, IStream * pStm)
{
DWORD mshlflags;
IUnknown *object;
DWORD constant;
GUID unknown_guid;
HRESULT hres;
TRACE ("(%p)\n", pStm);
hres = IStream_Read (pStm, &mshlflags, sizeof (mshlflags), NULL);
if (hres != S_OK) return STG_E_READFAULT;
hres = IStream_Read (pStm, &object, sizeof (object), NULL);
if (hres != S_OK) return STG_E_READFAULT;
if (sizeof(object) == sizeof(DWORD))
{
hres = IStream_Read (pStm, &constant, sizeof (constant), NULL);
if (hres != S_OK) return STG_E_READFAULT;
if (constant != 0)
FIXME("constant is 0x%x instead of 0\n", constant);
}
hres = IStream_Read (pStm, &unknown_guid, sizeof (unknown_guid), NULL);
if (hres != S_OK) return STG_E_READFAULT;
IUnknown_Release(object);
return S_OK;
}
static HRESULT WINAPI FTMarshalImpl_DisconnectObject (LPMARSHAL iface, DWORD dwReserved)
{
TRACE ("()\n");
/* nothing to do */
return S_OK;
}
static const IMarshalVtbl ftmvtbl =
{
FTMarshalImpl_QueryInterface,
FTMarshalImpl_AddRef,
FTMarshalImpl_Release,
FTMarshalImpl_GetUnmarshalClass,
FTMarshalImpl_GetMarshalSizeMax,
FTMarshalImpl_MarshalInterface,
FTMarshalImpl_UnmarshalInterface,
FTMarshalImpl_ReleaseMarshalData,
FTMarshalImpl_DisconnectObject
};
/***********************************************************************
* CoCreateFreeThreadedMarshaler [OLE32.@]
*
* Creates a free-threaded marshaler.
*
* PARAMS
* punkOuter [I] Optional. Outer unknown.
* ppunkMarshal [O] On return, the inner unknown of the created free-threaded marshaler.
*
* RETURNS
* Success: S_OK
* Failure: E_OUTOFMEMORY if no memory available to create object.
*
* NOTES
* Objects that ensure their state is maintained consistent when used by
* multiple threads and reference no single-threaded objects are known as
* free-threaded. The free-threaded marshaler enables these objects to be
* efficiently marshaled within the same process, by not creating proxies
* (as they aren't needed for the object to be safely used), whilst still
* allowing the object to be used in inter-process and inter-machine contexts.
*/
HRESULT WINAPI CoCreateFreeThreadedMarshaler (LPUNKNOWN punkOuter, LPUNKNOWN * ppunkMarshal)
{
FTMarshalImpl *ftm;
TRACE ("(%p %p)\n", punkOuter, ppunkMarshal);
ftm = HeapAlloc (GetProcessHeap (), 0, sizeof (FTMarshalImpl));
if (!ftm)
return E_OUTOFMEMORY;
ftm->IUnknown_inner.lpVtbl = &iunkvt;
ftm->IMarshal_iface.lpVtbl = &ftmvtbl;
ftm->ref = 1;
ftm->outer_unk = punkOuter ? punkOuter : &ftm->IUnknown_inner;
*ppunkMarshal = &ftm->IUnknown_inner;
return S_OK;
}
static HRESULT WINAPI FTMarshalCF_QueryInterface(LPCLASSFACTORY iface,
REFIID riid, LPVOID *ppv)
{

View File

@ -10,7 +10,7 @@
@ stdcall CoAllowSetForegroundWindow(ptr ptr)
@ stdcall CoBuildVersion()
@ stdcall CoCopyProxy(ptr ptr) combase.CoCopyProxy
@ stdcall CoCreateFreeThreadedMarshaler(ptr ptr)
@ stdcall CoCreateFreeThreadedMarshaler(ptr ptr) combase.CoCreateFreeThreadedMarshaler
@ stdcall CoCreateGuid(ptr) combase.CoCreateGuid
@ stdcall CoCreateInstance(ptr ptr long ptr ptr) combase.CoCreateInstance
@ stdcall CoCreateInstanceEx(ptr ptr long ptr long ptr)