Commit 475b2d6b authored by Piotr Caban's avatar Piotr Caban Committed by Alexandre Julliard

ole32: Make standard marshaler responsible for marshaling OBJREF header.

parent 862ea507
......@@ -392,10 +392,21 @@ static HRESULT WINAPI Proxy_GetMarshalSizeMax(
IMarshal *iface, REFIID riid, void* pv, DWORD dwDestContext,
void* pvDestContext, DWORD mshlflags, DWORD* pSize)
{
*pSize = sizeof(STDOBJREF);
*pSize = FIELD_OFFSET(OBJREF, u_objref.u_standard.saResAddr.aStringArray);
return S_OK;
}
static void fill_std_objref(OBJREF *objref, const GUID *iid, STDOBJREF *std)
{
objref->signature = OBJREF_SIGNATURE;
objref->flags = OBJREF_STANDARD;
objref->iid = *iid;
if(std)
objref->u_objref.u_standard.std = *std;
memset(&objref->u_objref.u_standard.saResAddr, 0,
sizeof(objref->u_objref.u_standard.saResAddr));
}
static HRESULT WINAPI Proxy_MarshalInterface(
LPMARSHAL iface, IStream *pStm, REFIID riid, void* pv, DWORD dwDestContext,
void* pvDestContext, DWORD mshlflags)
......@@ -459,12 +470,16 @@ static HRESULT WINAPI Proxy_MarshalInterface(
if (SUCCEEDED(hr))
{
OBJREF objref;
TRACE("writing stdobjref: flags = %04x cPublicRefs = %d oxid = %s oid = %s ipid = %s\n",
stdobjref.flags, stdobjref.cPublicRefs,
wine_dbgstr_longlong(stdobjref.oxid),
wine_dbgstr_longlong(stdobjref.oid),
debugstr_guid(&stdobjref.ipid));
hr = IStream_Write(pStm, &stdobjref, sizeof(stdobjref), NULL);
fill_std_objref(&objref, riid, &stdobjref);
hr = IStream_Write(pStm, &objref, FIELD_OFFSET(OBJREF,
u_objref.u_standard.saResAddr.aStringArray), NULL);
}
}
else
......@@ -490,7 +505,11 @@ static HRESULT WINAPI Proxy_MarshalInterface(
1, &iid, &qiresults);
if (SUCCEEDED(hr))
{
hr = IStream_Write(pStm, &qiresults->std, sizeof(qiresults->std), NULL);
OBJREF objref;
fill_std_objref(&objref, riid, &qiresults->std);
hr = IStream_Write(pStm, &objref, FIELD_OFFSET(OBJREF,
u_objref.u_standard.saResAddr.aStringArray), NULL);
if (FAILED(hr))
{
REMINTERFACEREF rif;
......@@ -1277,7 +1296,7 @@ StdMarshalImpl_GetMarshalSizeMax(
IMarshal *iface, REFIID riid, void* pv, DWORD dwDestContext,
void* pvDestContext, DWORD mshlflags, DWORD* pSize)
{
*pSize = sizeof(STDOBJREF);
*pSize = FIELD_OFFSET(OBJREF, u_objref.u_standard.saResAddr.aStringArray);
return S_OK;
}
......@@ -1286,10 +1305,10 @@ StdMarshalImpl_MarshalInterface(
IMarshal *iface, IStream *pStm,REFIID riid, void* pv, DWORD dest_context,
void* dest_context_data, DWORD mshlflags)
{
STDOBJREF stdobjref;
ULONG res;
HRESULT hres;
APARTMENT *apt;
OBJREF objref;
TRACE("(...,%s,...)\n", debugstr_guid(riid));
......@@ -1302,7 +1321,9 @@ StdMarshalImpl_MarshalInterface(
/* make sure this apartment can be reached from other threads / processes */
RPC_StartRemoting(apt);
hres = marshal_object(apt, &stdobjref, riid, pv, dest_context, dest_context_data, mshlflags);
fill_std_objref(&objref, riid, NULL);
hres = marshal_object(apt, &objref.u_objref.u_standard.std, riid,
pv, dest_context, dest_context_data, mshlflags);
apartment_release(apt);
if (hres != S_OK)
{
......@@ -1310,7 +1331,8 @@ StdMarshalImpl_MarshalInterface(
return hres;
}
return IStream_Write(pStm, &stdobjref, sizeof(stdobjref), &res);
return IStream_Write(pStm, &objref,
FIELD_OFFSET(OBJREF, u_objref.u_standard.saResAddr.aStringArray), &res);
}
/* helper for StdMarshalImpl_UnmarshalInterface - does the unmarshaling with
......@@ -1385,12 +1407,11 @@ static HRESULT unmarshal_object(const STDOBJREF *stdobjref, APARTMENT *apt,
return hr;
}
static HRESULT WINAPI
StdMarshalImpl_UnmarshalInterface(IMarshal *iface, IStream *pStm, REFIID riid, void **ppv)
static HRESULT std_unmarshal_interface(MSHCTX dest_context, void *dest_context_data,
IStream *pStm, REFIID riid, void **ppv)
{
StdMarshalImpl *This = impl_from_StdMarshal(iface);
struct stub_manager *stubmgr = NULL;
STDOBJREF stdobjref;
struct OR_STANDARD obj;
ULONG res;
HRESULT hres;
APARTMENT *apt;
......@@ -1407,7 +1428,7 @@ StdMarshalImpl_UnmarshalInterface(IMarshal *iface, IStream *pStm, REFIID riid, v
}
/* read STDOBJREF from wire */
hres = IStream_Read(pStm, &stdobjref, sizeof(stdobjref), &res);
hres = IStream_Read(pStm, &obj, FIELD_OFFSET(struct OR_STANDARD, saResAddr.aStringArray), &res);
if (hres != S_OK)
{
apartment_release(apt);
......@@ -1421,8 +1442,14 @@ StdMarshalImpl_UnmarshalInterface(IMarshal *iface, IStream *pStm, REFIID riid, v
return hres;
}
if (obj.saResAddr.wNumEntries)
{
ERR("unsupported size of DUALSTRINGARRAY\n");
return E_NOTIMPL;
}
/* check if we're marshalling back to ourselves */
if ((oxid == stdobjref.oxid) && (stubmgr = get_stub_manager(apt, stdobjref.oid)))
if ((oxid == 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);
......@@ -1430,8 +1457,8 @@ StdMarshalImpl_UnmarshalInterface(IMarshal *iface, IStream *pStm, REFIID riid, v
hres = IUnknown_QueryInterface(stubmgr->object, riid, ppv);
/* unref the ifstub. FIXME: only do this on success? */
if (!stub_manager_is_table_marshaled(stubmgr, &stdobjref.ipid))
stub_manager_ext_release(stubmgr, stdobjref.cPublicRefs, stdobjref.flags & SORFP_TABLEWEAK, FALSE);
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);
......@@ -1443,28 +1470,28 @@ StdMarshalImpl_UnmarshalInterface(IMarshal *iface, IStream *pStm, REFIID riid, v
* 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(stdobjref.oxid, TRUE)))
if ((stub_apt = apartment_findfromoxid(obj.std.oxid, TRUE)))
{
if ((stubmgr = get_stub_manager(stub_apt, stdobjref.oid)))
if ((stubmgr = get_stub_manager(stub_apt, obj.std.oid)))
{
if (!stub_manager_notify_unmarshal(stubmgr, &stdobjref.ipid))
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(stdobjref.oxid),
wine_dbgstr_longlong(stdobjref.oid));
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(stdobjref.oxid));
wine_dbgstr_longlong(obj.std.oxid));
if (hres == S_OK)
hres = unmarshal_object(&stdobjref, apt, This->dest_context,
This->dest_context_data, riid,
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);
......@@ -1478,40 +1505,74 @@ StdMarshalImpl_UnmarshalInterface(IMarshal *iface, IStream *pStm, REFIID riid, v
}
static HRESULT WINAPI
StdMarshalImpl_ReleaseMarshalData(IMarshal *iface, IStream *pStm)
StdMarshalImpl_UnmarshalInterface(IMarshal *iface, IStream *pStm, REFIID riid, void **ppv)
{
STDOBJREF stdobjref;
StdMarshalImpl *This = impl_from_StdMarshal(iface);
OBJREF objref;
HRESULT hr;
ULONG res;
hr = IStream_Read(pStm, &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;
}
if (objref.signature != OBJREF_SIGNATURE)
{
ERR("Bad OBJREF signature 0x%08x\n", objref.signature);
return RPC_E_INVALID_OBJREF;
}
if (!(objref.flags & OBJREF_STANDARD))
{
FIXME("unsupported objref.flags = %x\n", objref.flags);
return E_NOTIMPL;
}
return std_unmarshal_interface(This->dest_context,
This->dest_context_data, pStm, riid, ppv);
}
static HRESULT std_release_marshal_data(IStream *pStm)
{
struct OR_STANDARD obj;
ULONG res;
HRESULT hres;
struct stub_manager *stubmgr;
APARTMENT *apt;
TRACE("iface=%p, pStm=%p\n", iface, pStm);
hres = IStream_Read(pStm, &stdobjref, sizeof(stdobjref), &res);
hres = IStream_Read(pStm, &obj, FIELD_OFFSET(struct OR_STANDARD, saResAddr.aStringArray), &res);
if (hres != S_OK) return STG_E_READFAULT;
if (obj.saResAddr.wNumEntries)
{
ERR("unsupported size of DUALSTRINGARRAY\n");
return E_NOTIMPL;
}
TRACE("oxid = %s, oid = %s, ipid = %s\n",
wine_dbgstr_longlong(stdobjref.oxid),
wine_dbgstr_longlong(stdobjref.oid),
wine_dbgstr_guid(&stdobjref.ipid));
wine_dbgstr_longlong(obj.std.oxid),
wine_dbgstr_longlong(obj.std.oid),
wine_dbgstr_guid(&obj.std.ipid));
if (!(apt = apartment_findfromoxid(stdobjref.oxid, TRUE)))
if (!(apt = apartment_findfromoxid(obj.std.oxid, TRUE)))
{
WARN("Could not map OXID %s to apartment object\n",
wine_dbgstr_longlong(stdobjref.oxid));
wine_dbgstr_longlong(obj.std.oxid));
return RPC_E_INVALID_OBJREF;
}
if (!(stubmgr = get_stub_manager(apt, stdobjref.oid)))
if (!(stubmgr = get_stub_manager(apt, obj.std.oid)))
{
apartment_release(apt);
ERR("could not map object ID to stub manager, oxid=%s, oid=%s\n",
wine_dbgstr_longlong(stdobjref.oxid), wine_dbgstr_longlong(stdobjref.oid));
wine_dbgstr_longlong(obj.std.oxid), wine_dbgstr_longlong(obj.std.oid));
return RPC_E_INVALID_OBJREF;
}
stub_manager_release_marshal_data(stubmgr, stdobjref.cPublicRefs, &stdobjref.ipid, stdobjref.flags & SORFP_TABLEWEAK);
stub_manager_release_marshal_data(stubmgr, obj.std.cPublicRefs, &obj.std.ipid, obj.std.flags & SORFP_TABLEWEAK);
stub_manager_int_release(stubmgr);
apartment_release(apt);
......@@ -1520,6 +1581,37 @@ StdMarshalImpl_ReleaseMarshalData(IMarshal *iface, IStream *pStm)
}
static HRESULT WINAPI
StdMarshalImpl_ReleaseMarshalData(IMarshal *iface, IStream *pStm)
{
OBJREF objref;
HRESULT hr;
ULONG res;
TRACE("iface=%p, pStm=%p\n", iface, pStm);
hr = IStream_Read(pStm, &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;
}
if (objref.signature != OBJREF_SIGNATURE)
{
ERR("Bad OBJREF signature 0x%08x\n", objref.signature);
return RPC_E_INVALID_OBJREF;
}
if (!(objref.flags & OBJREF_STANDARD))
{
FIXME("unsupported objref.flags = %x\n", objref.flags);
return E_NOTIMPL;
}
return std_release_marshal_data(pStm);
}
static HRESULT WINAPI
StdMarshalImpl_DisconnectObject(IMarshal *iface, DWORD dwReserved)
{
FIXME("(), stub!\n");
......@@ -1652,7 +1744,8 @@ static HRESULT get_unmarshaler_from_stream(IStream *stream, IMarshal **marshal,
if (objref.flags & OBJREF_STANDARD)
{
TRACE("Using standard unmarshaling\n");
hr = StdMarshalImpl_Construct(&IID_IMarshal, 0, NULL, (LPVOID*)marshal);
*marshal = NULL;
return S_FALSE;
}
else if (objref.flags & OBJREF_CUSTOM)
{
......@@ -1728,12 +1821,8 @@ HRESULT WINAPI CoGetMarshalSizeMax(ULONG *pulSize, REFIID riid, IUnknown *pUnk,
hr = IMarshal_GetMarshalSizeMax(pMarshal, riid, pUnk, dwDestContext,
pvDestContext, mshlFlags, pulSize);
if (IsEqualCLSID(&marshaler_clsid, &CLSID_StdMarshal))
/* add on the size of the common header */
*pulSize += FIELD_OFFSET(OBJREF, u_objref);
else
/* custom marshaling: add on the size of the whole OBJREF structure
* like native does */
if (!IsEqualCLSID(&marshaler_clsid, &CLSID_StdMarshal))
/* add on the size of the whole OBJREF structure like native does */
*pulSize += sizeof(OBJREF);
IMarshal_Release(pMarshal);
......@@ -1791,7 +1880,6 @@ HRESULT WINAPI CoMarshalInterface(IStream *pStream, REFIID riid, IUnknown *pUnk,
{
HRESULT hr;
CLSID marshaler_clsid;
OBJREF objref;
LPMARSHAL pMarshal;
TRACE("(%p, %s, %p, %x, %p, ", pStream, debugstr_guid(riid), pUnk,
......@@ -1802,9 +1890,6 @@ HRESULT WINAPI CoMarshalInterface(IStream *pStream, REFIID riid, IUnknown *pUnk,
if (!pUnk || !pStream)
return E_INVALIDARG;
objref.signature = OBJREF_SIGNATURE;
objref.iid = *riid;
/* get the marshaler for the specified interface */
hr = get_marshaler(riid, pUnk, dwDestContext, pvDestContext, mshlFlags, &pMarshal);
if (hr != S_OK)
......@@ -1825,19 +1910,14 @@ HRESULT WINAPI CoMarshalInterface(IStream *pStream, REFIID riid, IUnknown *pUnk,
if (IsEqualCLSID(&marshaler_clsid, &CLSID_StdMarshal))
{
TRACE("Using standard marshaling\n");
objref.flags = OBJREF_STANDARD;
/* write the common OBJREF header to the stream */
hr = IStream_Write(pStream, &objref, FIELD_OFFSET(OBJREF, u_objref), NULL);
if (hr != S_OK)
{
ERR("Failed to write OBJREF header to stream, 0x%08x\n", hr);
goto cleanup;
}
}
else
{
OBJREF objref;
TRACE("Using custom marshaling\n");
objref.signature = OBJREF_SIGNATURE;
objref.iid = *riid;
objref.flags = OBJREF_CUSTOM;
objref.u_objref.u_custom.clsid = marshaler_clsid;
objref.u_objref.u_custom.cbExtension = 0;
......@@ -1912,13 +1992,20 @@ HRESULT WINAPI CoUnmarshalInterface(IStream *pStream, REFIID riid, LPVOID *ppv)
return E_INVALIDARG;
hr = get_unmarshaler_from_stream(pStream, &pMarshal, &iid);
if (hr != S_OK)
return hr;
/* call the helper object to do the actual unmarshaling */
hr = IMarshal_UnmarshalInterface(pMarshal, pStream, &iid, (LPVOID*)&object);
if (hr != S_OK)
ERR("IMarshal::UnmarshalInterface failed, 0x%08x\n", hr);
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)
{
......@@ -1938,8 +2025,6 @@ HRESULT WINAPI CoUnmarshalInterface(IStream *pStream, REFIID riid, LPVOID *ppv)
}
}
IMarshal_Release(pMarshal);
TRACE("completed with hr 0x%x\n", hr);
return hr;
......@@ -1976,6 +2061,13 @@ HRESULT WINAPI CoReleaseMarshalData(IStream *pStream)
TRACE("(%p)\n", pStream);
hr = get_unmarshaler_from_stream(pStream, &pMarshal, NULL);
if (hr == S_FALSE)
{
hr = std_release_marshal_data(pStream);
if (hr != S_OK)
ERR("StdMarshal ReleaseMarshalData failed with error 0x%08x\n", hr);
return hr;
}
if (hr != S_OK)
return hr;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment