mirror of
https://gitlab.winehq.org/wine/wine.git
synced 2024-11-19 17:06:04 -07:00
combase: Implement RoGetAgileReference().
This commit is contained in:
parent
babb8730cc
commit
a387549a27
Notes:
Alexandre Julliard
2024-11-08 21:36:34 +01:00
Approved-by: Huw Davies (@huw) Approved-by: Alexandre Julliard (@julliard) Merge-Request: https://gitlab.winehq.org/wine/wine/merge_requests/6762
5 changed files with 192 additions and 1 deletions
|
@ -292,7 +292,7 @@
|
|||
@ stub RoFreeParameterizedTypeExtra
|
||||
@ stub RoGetActivatableClassRegistration
|
||||
@ stdcall RoGetActivationFactory(ptr ptr ptr)
|
||||
@ stub RoGetAgileReference
|
||||
@ stdcall RoGetAgileReference(long ptr ptr ptr)
|
||||
@ stdcall RoGetApartmentIdentifier(ptr)
|
||||
@ stub RoGetErrorReportingFlags
|
||||
@ stub RoGetMatchingRestrictedErrorInfo
|
||||
|
|
|
@ -96,6 +96,7 @@ struct tlsdata
|
|||
};
|
||||
|
||||
extern HRESULT WINAPI InternalTlsAllocData(struct tlsdata **data);
|
||||
extern BOOL WINAPI InternalIsProcessInitialized(void);
|
||||
|
||||
static inline HRESULT com_get_tlsdata(struct tlsdata **data)
|
||||
{
|
||||
|
|
|
@ -233,6 +233,188 @@ HRESULT WINAPI RoActivateInstance(HSTRING classid, IInspectable **instance)
|
|||
return hr;
|
||||
}
|
||||
|
||||
struct agile_reference
|
||||
{
|
||||
IAgileReference IAgileReference_iface;
|
||||
enum AgileReferenceOptions option;
|
||||
IStream *marshal_stream;
|
||||
CRITICAL_SECTION cs;
|
||||
IUnknown *obj;
|
||||
LONG ref;
|
||||
};
|
||||
|
||||
static HRESULT marshal_object_in_agile_reference(struct agile_reference *ref, REFIID riid, IUnknown *obj)
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
hr = CreateStreamOnHGlobal(0, TRUE, &ref->marshal_stream);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
hr = CoMarshalInterface(ref->marshal_stream, riid, obj, MSHCTX_INPROC, NULL, MSHLFLAGS_TABLESTRONG);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
IStream_Release(ref->marshal_stream);
|
||||
ref->marshal_stream = NULL;
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
|
||||
static inline struct agile_reference *impl_from_IAgileReference(IAgileReference *iface)
|
||||
{
|
||||
return CONTAINING_RECORD(iface, struct agile_reference, IAgileReference_iface);
|
||||
}
|
||||
|
||||
static HRESULT WINAPI agile_ref_QueryInterface(IAgileReference *iface, REFIID riid, void **obj)
|
||||
{
|
||||
TRACE("(%p, %s, %p)\n", iface, debugstr_guid(riid), obj);
|
||||
|
||||
if (!riid || !obj) return E_INVALIDARG;
|
||||
|
||||
if (IsEqualGUID(riid, &IID_IUnknown)
|
||||
|| IsEqualGUID(riid, &IID_IAgileObject)
|
||||
|| IsEqualGUID(riid, &IID_IAgileReference))
|
||||
{
|
||||
IUnknown_AddRef(iface);
|
||||
*obj = iface;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
*obj = NULL;
|
||||
FIXME("interface %s is not implemented\n", debugstr_guid(riid));
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
static ULONG WINAPI agile_ref_AddRef(IAgileReference *iface)
|
||||
{
|
||||
struct agile_reference *impl = impl_from_IAgileReference(iface);
|
||||
return InterlockedIncrement(&impl->ref);
|
||||
}
|
||||
|
||||
static ULONG WINAPI agile_ref_Release(IAgileReference *iface)
|
||||
{
|
||||
struct agile_reference *impl = impl_from_IAgileReference(iface);
|
||||
LONG ref = InterlockedDecrement(&impl->ref);
|
||||
|
||||
if (!ref)
|
||||
{
|
||||
TRACE("destroying %p\n", iface);
|
||||
|
||||
if (impl->obj)
|
||||
IUnknown_Release(impl->obj);
|
||||
|
||||
if (impl->marshal_stream)
|
||||
{
|
||||
LARGE_INTEGER zero = {0};
|
||||
|
||||
IStream_Seek(impl->marshal_stream, zero, STREAM_SEEK_SET, NULL);
|
||||
CoReleaseMarshalData(impl->marshal_stream);
|
||||
IStream_Release(impl->marshal_stream);
|
||||
}
|
||||
DeleteCriticalSection(&impl->cs);
|
||||
free(impl);
|
||||
}
|
||||
|
||||
return ref;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI agile_ref_Resolve(IAgileReference *iface, REFIID riid, void **obj)
|
||||
{
|
||||
struct agile_reference *impl = impl_from_IAgileReference(iface);
|
||||
LARGE_INTEGER zero = {0};
|
||||
HRESULT hr;
|
||||
|
||||
TRACE("(%p, %s, %p)\n", iface, debugstr_guid(riid), obj);
|
||||
|
||||
EnterCriticalSection(&impl->cs);
|
||||
if (impl->option == AGILEREFERENCE_DELAYEDMARSHAL && impl->marshal_stream == NULL)
|
||||
{
|
||||
if (FAILED(hr = marshal_object_in_agile_reference(impl, riid, impl->obj)))
|
||||
{
|
||||
LeaveCriticalSection(&impl->cs);
|
||||
return hr;
|
||||
}
|
||||
|
||||
IUnknown_Release(impl->obj);
|
||||
impl->obj = NULL;
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr = IStream_Seek(impl->marshal_stream, zero, STREAM_SEEK_SET, NULL)))
|
||||
hr = CoUnmarshalInterface(impl->marshal_stream, riid, obj);
|
||||
|
||||
LeaveCriticalSection(&impl->cs);
|
||||
return hr;
|
||||
}
|
||||
|
||||
static const IAgileReferenceVtbl agile_ref_vtbl =
|
||||
{
|
||||
agile_ref_QueryInterface,
|
||||
agile_ref_AddRef,
|
||||
agile_ref_Release,
|
||||
agile_ref_Resolve,
|
||||
};
|
||||
|
||||
/***********************************************************************
|
||||
* RoGetAgileReference (combase.@)
|
||||
*/
|
||||
HRESULT WINAPI RoGetAgileReference(enum AgileReferenceOptions option, REFIID riid, IUnknown *obj,
|
||||
IAgileReference **agile_reference)
|
||||
{
|
||||
struct agile_reference *impl;
|
||||
IUnknown *unknown;
|
||||
HRESULT hr;
|
||||
|
||||
TRACE("(%d, %s, %p, %p).\n", option, debugstr_guid(riid), obj, agile_reference);
|
||||
|
||||
if (option != AGILEREFERENCE_DEFAULT && option != AGILEREFERENCE_DELAYEDMARSHAL)
|
||||
return E_INVALIDARG;
|
||||
|
||||
if (!InternalIsProcessInitialized())
|
||||
{
|
||||
ERR("Apartment not initialized\n");
|
||||
return CO_E_NOTINITIALIZED;
|
||||
}
|
||||
|
||||
hr = IUnknown_QueryInterface(obj, riid, (void **)&unknown);
|
||||
if (FAILED(hr))
|
||||
return E_NOINTERFACE;
|
||||
IUnknown_Release(unknown);
|
||||
|
||||
hr = IUnknown_QueryInterface(obj, &IID_INoMarshal, (void **)&unknown);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
IUnknown_Release(unknown);
|
||||
return CO_E_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
impl = calloc(1, sizeof(*impl));
|
||||
if (!impl)
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
impl->IAgileReference_iface.lpVtbl = &agile_ref_vtbl;
|
||||
impl->option = option;
|
||||
impl->ref = 1;
|
||||
|
||||
if (option == AGILEREFERENCE_DEFAULT)
|
||||
{
|
||||
if (FAILED(hr = marshal_object_in_agile_reference(impl, riid, obj)))
|
||||
{
|
||||
free(impl);
|
||||
return hr;
|
||||
}
|
||||
}
|
||||
else if (option == AGILEREFERENCE_DELAYEDMARSHAL)
|
||||
{
|
||||
impl->obj = obj;
|
||||
IUnknown_AddRef(impl->obj);
|
||||
}
|
||||
|
||||
InitializeCriticalSection(&impl->cs);
|
||||
|
||||
*agile_reference = &impl->IAgileReference_iface;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* RoGetApartmentIdentifier (combase.@)
|
||||
*/
|
||||
|
|
|
@ -254,6 +254,7 @@
|
|||
@ stdcall RegisterDragDrop(long ptr)
|
||||
@ stdcall ReleaseStgMedium(ptr)
|
||||
@ stdcall RevokeDragDrop(long)
|
||||
@ stdcall RoGetAgileReference(long ptr ptr ptr) combase.RoGetAgileReference
|
||||
@ stdcall SNB_UserFree(ptr ptr)
|
||||
@ stdcall SNB_UserMarshal(ptr ptr ptr)
|
||||
@ stdcall SNB_UserSize(ptr long ptr)
|
||||
|
|
|
@ -44,7 +44,14 @@ typedef struct tagServerInformation
|
|||
UINT64 ui64ServerAddress;
|
||||
} ServerInformation, *PServerInformation;
|
||||
|
||||
enum AgileReferenceOptions
|
||||
{
|
||||
AGILEREFERENCE_DEFAULT,
|
||||
AGILEREFERENCE_DELAYEDMARSHAL
|
||||
};
|
||||
|
||||
HRESULT WINAPI CoDecodeProxy(DWORD client_pid, UINT64 proxy_addr, ServerInformation *server_info);
|
||||
HRESULT WINAPI RoGetAgileReference(enum AgileReferenceOptions options, REFIID riid, IUnknown *obj, IAgileReference **agile_reference);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue