combase: Move CoUnmarshalInterface().
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:
parent
1a6afac0e4
commit
59a724d0cd
|
@ -1270,6 +1270,11 @@ HWND WINAPI apartment_getwindow(const struct apartment *apt)
|
|||
return apt->win;
|
||||
}
|
||||
|
||||
OXID apartment_getoxid(const struct apartment *apt)
|
||||
{
|
||||
return apt->oxid;
|
||||
}
|
||||
|
||||
void apartment_global_cleanup(void)
|
||||
{
|
||||
if (apt_win_class)
|
||||
|
|
|
@ -166,7 +166,7 @@
|
|||
@ stdcall CoUninitialize()
|
||||
@ stub CoUnloadingWOW
|
||||
@ stdcall CoUnmarshalHresult(ptr ptr)
|
||||
@ stdcall CoUnmarshalInterface(ptr ptr ptr) ole32.CoUnmarshalInterface
|
||||
@ stdcall CoUnmarshalInterface(ptr ptr ptr)
|
||||
@ stub CoVrfCheckThreadState
|
||||
@ stub CoVrfGetThreadState
|
||||
@ stub CoVrfReleaseThreadState
|
||||
|
|
|
@ -106,6 +106,7 @@ HWND WINAPI apartment_getwindow(const struct apartment *apt) DECLSPEC_HIDDEN;
|
|||
HRESULT WINAPI apartment_createwindowifneeded(struct apartment *apt) DECLSPEC_HIDDEN;
|
||||
void apartment_freeunusedlibraries(struct apartment *apt, DWORD unload_delay) DECLSPEC_HIDDEN;
|
||||
void apartment_global_cleanup(void) DECLSPEC_HIDDEN;
|
||||
OXID apartment_getoxid(const struct apartment *apt) DECLSPEC_HIDDEN;
|
||||
|
||||
/* RpcSs interface */
|
||||
HRESULT rpcss_get_next_seqid(DWORD *id) DECLSPEC_HIDDEN;
|
||||
|
@ -224,3 +225,5 @@ ULONG WINAPI stub_manager_ext_addref(struct stub_manager *m, ULONG refs, BOOL ta
|
|||
ULONG WINAPI stub_manager_ext_release(struct stub_manager *m, ULONG refs, BOOL tableweak, BOOL last_unlock_releases) DECLSPEC_HIDDEN;
|
||||
struct stub_manager * WINAPI get_stub_manager(struct apartment *apt, OID oid);
|
||||
void WINAPI stub_manager_release_marshal_data(struct stub_manager *m, ULONG refs, const IPID *ipid, BOOL tableweak);
|
||||
BOOL WINAPI stub_manager_is_table_marshaled(struct stub_manager *m, const IPID *ipid);
|
||||
BOOL WINAPI stub_manager_notify_unmarshal(struct stub_manager *m, const IPID *ipid);
|
||||
|
|
|
@ -29,6 +29,11 @@
|
|||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(ole);
|
||||
|
||||
HRESULT WINAPI unmarshal_object(const STDOBJREF *stdobjref, struct apartment *apt,
|
||||
MSHCTX dest_context, void *dest_context_data,
|
||||
REFIID riid, const OXID_INFO *oxid_info,
|
||||
void **object);
|
||||
|
||||
/* private flag indicating that the object was marshaled as table-weak */
|
||||
#define SORFP_TABLEWEAK SORF_OXRES1
|
||||
|
||||
|
@ -648,3 +653,144 @@ HRESULT WINAPI CoReleaseMarshalData(IStream *stream)
|
|||
IMarshal_Release(marshal);
|
||||
return hr;
|
||||
}
|
||||
|
||||
static HRESULT std_unmarshal_interface(MSHCTX dest_context, void *dest_context_data,
|
||||
IStream *stream, REFIID riid, void **ppv)
|
||||
{
|
||||
struct stub_manager *stubmgr = NULL;
|
||||
struct OR_STANDARD obj;
|
||||
ULONG res;
|
||||
HRESULT hres;
|
||||
struct apartment *apt, *stub_apt;
|
||||
|
||||
TRACE("(...,%s,....)\n", debugstr_guid(riid));
|
||||
|
||||
/* we need an apartment to unmarshal into */
|
||||
if (!(apt = apartment_get_current_or_mta()))
|
||||
{
|
||||
ERR("Apartment not initialized\n");
|
||||
return CO_E_NOTINITIALIZED;
|
||||
}
|
||||
|
||||
/* read STDOBJREF from wire */
|
||||
hres = IStream_Read(stream, &obj, FIELD_OFFSET(struct OR_STANDARD, saResAddr.aStringArray), &res);
|
||||
if (hres != S_OK)
|
||||
{
|
||||
apartment_release(apt);
|
||||
return STG_E_READFAULT;
|
||||
}
|
||||
|
||||
if (obj.saResAddr.wNumEntries)
|
||||
{
|
||||
ERR("unsupported size of DUALSTRINGARRAY\n");
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
/* check if we're marshalling back to ourselves */
|
||||
if ((apartment_getoxid(apt) == obj.std.oxid) && (stubmgr = get_stub_manager(apt, obj.std.oid)))
|
||||
{
|
||||
TRACE("Unmarshalling object marshalled in same apartment for iid %s, "
|
||||
"returning original object %p\n", debugstr_guid(riid), stubmgr->object);
|
||||
|
||||
hres = IUnknown_QueryInterface(stubmgr->object, riid, ppv);
|
||||
|
||||
/* unref the ifstub. FIXME: only do this on success? */
|
||||
if (!stub_manager_is_table_marshaled(stubmgr, &obj.std.ipid))
|
||||
stub_manager_ext_release(stubmgr, obj.std.cPublicRefs, obj.std.flags & SORFP_TABLEWEAK, FALSE);
|
||||
|
||||
stub_manager_int_release(stubmgr);
|
||||
apartment_release(apt);
|
||||
return hres;
|
||||
}
|
||||
|
||||
/* notify stub manager about unmarshal if process-local object.
|
||||
* note: if the oxid is not found then we and native will quite happily
|
||||
* ignore table marshaling and normal marshaling rules regarding number of
|
||||
* unmarshals, etc, but if you abuse these rules then your proxy could end
|
||||
* up returning RPC_E_DISCONNECTED. */
|
||||
if ((stub_apt = apartment_findfromoxid(obj.std.oxid)))
|
||||
{
|
||||
if ((stubmgr = get_stub_manager(stub_apt, obj.std.oid)))
|
||||
{
|
||||
if (!stub_manager_notify_unmarshal(stubmgr, &obj.std.ipid))
|
||||
hres = CO_E_OBJNOTCONNECTED;
|
||||
}
|
||||
else
|
||||
{
|
||||
WARN("Couldn't find object for OXID %s, OID %s, assuming disconnected\n",
|
||||
wine_dbgstr_longlong(obj.std.oxid),
|
||||
wine_dbgstr_longlong(obj.std.oid));
|
||||
hres = CO_E_OBJNOTCONNECTED;
|
||||
}
|
||||
}
|
||||
else
|
||||
TRACE("Treating unmarshal from OXID %s as inter-process\n",
|
||||
wine_dbgstr_longlong(obj.std.oxid));
|
||||
|
||||
if (hres == S_OK)
|
||||
hres = unmarshal_object(&obj.std, apt, dest_context,
|
||||
dest_context_data, riid,
|
||||
stubmgr ? &stubmgr->oxid_info : NULL, ppv);
|
||||
|
||||
if (stubmgr) stub_manager_int_release(stubmgr);
|
||||
if (stub_apt) apartment_release(stub_apt);
|
||||
|
||||
if (hres != S_OK) WARN("Failed with error 0x%08x\n", hres);
|
||||
else TRACE("Successfully created proxy %p\n", *ppv);
|
||||
|
||||
apartment_release(apt);
|
||||
return hres;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* CoUnmarshalInterface (combase.@)
|
||||
*/
|
||||
HRESULT WINAPI CoUnmarshalInterface(IStream *stream, REFIID riid, void **ppv)
|
||||
{
|
||||
IMarshal *marshal;
|
||||
IUnknown *object;
|
||||
HRESULT hr;
|
||||
IID iid;
|
||||
|
||||
TRACE("%p, %s, %p\n", stream, debugstr_guid(riid), ppv);
|
||||
|
||||
if (!stream || !ppv)
|
||||
return E_INVALIDARG;
|
||||
|
||||
hr = get_unmarshaler_from_stream(stream, &marshal, &iid);
|
||||
if (hr == S_FALSE)
|
||||
{
|
||||
hr = std_unmarshal_interface(0, NULL, stream, &iid, (void **)&object);
|
||||
if (hr != S_OK)
|
||||
ERR("StdMarshal UnmarshalInterface failed, hr %#x\n", hr);
|
||||
}
|
||||
else if (hr == S_OK)
|
||||
{
|
||||
/* call the helper object to do the actual unmarshaling */
|
||||
hr = IMarshal_UnmarshalInterface(marshal, stream, &iid, (void **)&object);
|
||||
IMarshal_Release(marshal);
|
||||
if (hr != S_OK)
|
||||
ERR("IMarshal::UnmarshalInterface failed, hr %#x\n", hr);
|
||||
}
|
||||
|
||||
if (hr == S_OK)
|
||||
{
|
||||
/* IID_NULL means use the interface ID of the marshaled object */
|
||||
if (!IsEqualIID(riid, &IID_NULL) && !IsEqualIID(riid, &iid))
|
||||
{
|
||||
TRACE("requested interface != marshalled interface, additional QI needed\n");
|
||||
hr = IUnknown_QueryInterface(object, riid, ppv);
|
||||
if (hr != S_OK)
|
||||
ERR("Couldn't query for interface %s, hr %#x\n", debugstr_guid(riid), hr);
|
||||
IUnknown_Release(object);
|
||||
}
|
||||
else
|
||||
{
|
||||
*ppv = object;
|
||||
}
|
||||
}
|
||||
|
||||
TRACE("completed with hr 0x%x\n", hr);
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
|
|
@ -95,7 +95,7 @@ static inline struct proxy_manager *impl_from_IClientSecurity( IClientSecurity *
|
|||
return CONTAINING_RECORD(iface, struct proxy_manager, IClientSecurity_iface);
|
||||
}
|
||||
|
||||
static HRESULT unmarshal_object(const STDOBJREF *stdobjref, struct apartment *apt,
|
||||
HRESULT WINAPI unmarshal_object(const STDOBJREF *stdobjref, struct apartment *apt,
|
||||
MSHCTX dest_context, void *dest_context_data,
|
||||
REFIID riid, const OXID_INFO *oxid_info,
|
||||
void **object);
|
||||
|
@ -1347,7 +1347,7 @@ StdMarshalImpl_MarshalInterface(
|
|||
/* helper for StdMarshalImpl_UnmarshalInterface - does the unmarshaling with
|
||||
* no questions asked about the rules surrounding same-apartment unmarshals
|
||||
* and table marshaling */
|
||||
static HRESULT unmarshal_object(const STDOBJREF *stdobjref, struct apartment *apt,
|
||||
HRESULT WINAPI unmarshal_object(const STDOBJREF *stdobjref, struct apartment *apt,
|
||||
MSHCTX dest_context, void *dest_context_data,
|
||||
REFIID riid, const OXID_INFO *oxid_info,
|
||||
void **object)
|
||||
|
@ -1698,145 +1698,6 @@ HRESULT WINAPI CoGetStandardMarshal(REFIID riid, IUnknown *pUnk,
|
|||
return StdMarshalImpl_Construct(&IID_IMarshal, dwDestContext, pvDestContext, (void**)ppMarshal);
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* get_unmarshaler_from_stream [internal]
|
||||
*
|
||||
* Creates an IMarshal* object according to the data marshaled to the stream.
|
||||
* The function leaves the stream pointer at the start of the data written
|
||||
* to the stream by the IMarshal* object.
|
||||
*/
|
||||
static HRESULT get_unmarshaler_from_stream(IStream *stream, IMarshal **marshal, IID *iid)
|
||||
{
|
||||
HRESULT hr;
|
||||
ULONG res;
|
||||
OBJREF objref;
|
||||
|
||||
/* read common OBJREF header */
|
||||
hr = IStream_Read(stream, &objref, FIELD_OFFSET(OBJREF, u_objref), &res);
|
||||
if (hr != S_OK || (res != FIELD_OFFSET(OBJREF, u_objref)))
|
||||
{
|
||||
ERR("Failed to read common OBJREF header, 0x%08x\n", hr);
|
||||
return STG_E_READFAULT;
|
||||
}
|
||||
|
||||
/* sanity check on header */
|
||||
if (objref.signature != OBJREF_SIGNATURE)
|
||||
{
|
||||
ERR("Bad OBJREF signature 0x%08x\n", objref.signature);
|
||||
return RPC_E_INVALID_OBJREF;
|
||||
}
|
||||
|
||||
if (iid) *iid = objref.iid;
|
||||
|
||||
/* FIXME: handler marshaling */
|
||||
if (objref.flags & OBJREF_STANDARD)
|
||||
{
|
||||
TRACE("Using standard unmarshaling\n");
|
||||
*marshal = NULL;
|
||||
return S_FALSE;
|
||||
}
|
||||
else if (objref.flags & OBJREF_CUSTOM)
|
||||
{
|
||||
ULONG custom_header_size = FIELD_OFFSET(OBJREF, u_objref.u_custom.pData) -
|
||||
FIELD_OFFSET(OBJREF, u_objref.u_custom);
|
||||
TRACE("Using custom unmarshaling\n");
|
||||
/* read constant sized OR_CUSTOM data from stream */
|
||||
hr = IStream_Read(stream, &objref.u_objref.u_custom,
|
||||
custom_header_size, &res);
|
||||
if (hr != S_OK || (res != custom_header_size))
|
||||
{
|
||||
ERR("Failed to read OR_CUSTOM header, 0x%08x\n", hr);
|
||||
return STG_E_READFAULT;
|
||||
}
|
||||
/* now create the marshaler specified in the stream */
|
||||
hr = CoCreateInstance(&objref.u_objref.u_custom.clsid, NULL,
|
||||
CLSCTX_INPROC_SERVER, &IID_IMarshal,
|
||||
(LPVOID*)marshal);
|
||||
}
|
||||
else
|
||||
{
|
||||
FIXME("Invalid or unimplemented marshaling type specified: %x\n",
|
||||
objref.flags);
|
||||
return RPC_E_INVALID_OBJREF;
|
||||
}
|
||||
|
||||
if (hr != S_OK)
|
||||
ERR("Failed to create marshal, 0x%08x\n", hr);
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* CoUnmarshalInterface [OLE32.@]
|
||||
*
|
||||
* Unmarshals an object from a stream by creating a proxy to the remote
|
||||
* object, if necessary.
|
||||
*
|
||||
* PARAMS
|
||||
*
|
||||
* pStream [I] Stream containing the marshaled object.
|
||||
* riid [I] Interface identifier of the object to create a proxy to.
|
||||
* ppv [O] Address where proxy will be stored.
|
||||
*
|
||||
* RETURNS
|
||||
*
|
||||
* Success: S_OK.
|
||||
* Failure: HRESULT code.
|
||||
*
|
||||
* SEE ALSO
|
||||
* CoMarshalInterface().
|
||||
*/
|
||||
HRESULT WINAPI CoUnmarshalInterface(IStream *pStream, REFIID riid, LPVOID *ppv)
|
||||
{
|
||||
HRESULT hr;
|
||||
LPMARSHAL pMarshal;
|
||||
IID iid;
|
||||
IUnknown *object;
|
||||
|
||||
TRACE("(%p, %s, %p)\n", pStream, debugstr_guid(riid), ppv);
|
||||
|
||||
if (!pStream || !ppv)
|
||||
return E_INVALIDARG;
|
||||
|
||||
hr = get_unmarshaler_from_stream(pStream, &pMarshal, &iid);
|
||||
if (hr == S_FALSE)
|
||||
{
|
||||
hr = std_unmarshal_interface(0, NULL, pStream, &iid, (void**)&object);
|
||||
if (hr != S_OK)
|
||||
ERR("StdMarshal UnmarshalInterface failed, 0x%08x\n", hr);
|
||||
}
|
||||
else if (hr == S_OK)
|
||||
{
|
||||
/* call the helper object to do the actual unmarshaling */
|
||||
hr = IMarshal_UnmarshalInterface(pMarshal, pStream, &iid, (LPVOID*)&object);
|
||||
IMarshal_Release(pMarshal);
|
||||
if (hr != S_OK)
|
||||
ERR("IMarshal::UnmarshalInterface failed, 0x%08x\n", hr);
|
||||
}
|
||||
|
||||
if (hr == S_OK)
|
||||
{
|
||||
/* IID_NULL means use the interface ID of the marshaled object */
|
||||
if (!IsEqualIID(riid, &IID_NULL) && !IsEqualIID(riid, &iid))
|
||||
{
|
||||
TRACE("requested interface != marshalled interface, additional QI needed\n");
|
||||
hr = IUnknown_QueryInterface(object, riid, ppv);
|
||||
if (hr != S_OK)
|
||||
ERR("Couldn't query for interface %s, hr = 0x%08x\n",
|
||||
debugstr_guid(riid), hr);
|
||||
IUnknown_Release(object);
|
||||
}
|
||||
else
|
||||
{
|
||||
*ppv = object;
|
||||
}
|
||||
}
|
||||
|
||||
TRACE("completed with hr 0x%x\n", hr);
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI StdMarshalCF_QueryInterface(LPCLASSFACTORY iface,
|
||||
REFIID riid, LPVOID *ppv)
|
||||
{
|
||||
|
|
|
@ -90,7 +90,7 @@
|
|||
@ stdcall CoUninitialize() combase.CoUninitialize
|
||||
@ stub CoUnloadingWOW
|
||||
@ stdcall CoUnmarshalHresult(ptr ptr) combase.CoUnmarshalHresult
|
||||
@ stdcall CoUnmarshalInterface(ptr ptr ptr)
|
||||
@ stdcall CoUnmarshalInterface(ptr ptr ptr) combase.CoUnmarshalInterface
|
||||
@ stdcall CoWaitForMultipleHandles(long long long ptr ptr) combase.CoWaitForMultipleHandles
|
||||
@ stdcall CreateAntiMoniker(ptr)
|
||||
@ stdcall CreateBindCtx(long ptr)
|
||||
|
@ -302,5 +302,6 @@
|
|||
@ stdcall Internal_apartment_disconnectproxies(ptr)
|
||||
@ stdcall Internal_RPC_ExecuteCall(ptr)
|
||||
@ stdcall marshal_object(ptr ptr ptr ptr long ptr long)
|
||||
@ stdcall unmarshal_object(ptr ptr long ptr ptr ptr ptr)
|
||||
@ stdcall RPC_CreateServerChannel(long ptr ptr)
|
||||
@ stdcall RPC_UnregisterInterface(ptr long)
|
||||
|
|
Loading…
Reference in New Issue