- Consolidate more stub creation details into register_ifstub.

- Replace the current wine_marshal_id structure with STDOBJREF for the
  on-the-wire format.
This commit is contained in:
Robert Shearman 2005-01-20 10:35:46 +00:00 committed by Alexandre Julliard
parent a47a0e3be7
commit 717eb8fff4
2 changed files with 87 additions and 72 deletions

View File

@ -28,8 +28,6 @@
*
* TODO list: (items bunched together depend on each other)
*
* - Once that's done, replace wine_marshal_id with STDOBJREF
*
* - Rewrite the CoLockObjectExternal code, it does totally the wrong
* thing currently (should be controlling the stub manager)
*

View File

@ -49,6 +49,9 @@ WINE_DEFAULT_DEBUG_CHANNEL(ole);
extern const CLSID CLSID_DfMarshal;
/* number of refs given out for normal marshaling */
#define NORMALEXTREFS 1 /* FIXME: this should be 5, but we have to wait for IRemUnknown support first */
/* Marshalling just passes a unique identifier to the remote client,
* that makes it possible to find the passed interface again.
*
@ -103,23 +106,41 @@ IRpcStubBuffer *mid_to_stubbuffer(wine_marshal_id *mid)
return ret;
}
/* creates a new stub manager and sets mid->oid when mid->oid == 0 */
static HRESULT register_ifstub(wine_marshal_id *mid, REFIID riid, IUnknown *obj, IRpcStubBuffer *stub, MSHLFLAGS mshlflags)
/* creates a new stub manager and sets stdobjref->oid when stdobjref->oid == 0 */
static HRESULT register_ifstub(APARTMENT *apt, STDOBJREF *stdobjref, REFIID riid, IUnknown *obj, MSHLFLAGS mshlflags)
{
struct stub_manager *manager = NULL;
struct ifstub *ifstub;
APARTMENT *apt;
BOOL tablemarshal;
IRpcStubBuffer *stub;
IPSFactoryBuffer *psfb;
HRESULT hr;
if (!(apt = COM_ApartmentFromOXID(mid->oxid, TRUE)))
hr = get_facbuf_for_iid(riid, &psfb);
if (hr != S_OK)
{
ERR("Could not map OXID %s to apartment object\n", wine_dbgstr_longlong(mid->oxid));
return E_UNEXPECTED;
ERR("couldn't get IPSFactory buffer for interface %s\n", debugstr_guid(riid));
return hr;
}
hr = IPSFactoryBuffer_CreateStub(psfb, riid, obj, &stub);
IPSFactoryBuffer_Release(psfb);
if (hr != S_OK)
{
ERR("Failed to create an IRpcStubBuffer from IPSFactory for %s\n", debugstr_guid(riid));
return hr;
}
if (mshlflags & MSHLFLAGS_NOPING)
stdobjref->flags = SORF_NOPING;
else
stdobjref->flags = SORF_NULL;
stdobjref->oxid = apt->oxid;
/* mid->oid of zero means create a new stub manager */
if (mid->oid && (manager = get_stub_manager(apt, mid->oid)))
if (stdobjref->oid && (manager = get_stub_manager(apt, stdobjref->oid)))
{
TRACE("registering new ifstub on pre-existing manager\n");
}
@ -129,12 +150,9 @@ static HRESULT register_ifstub(wine_marshal_id *mid, REFIID riid, IUnknown *obj,
manager = new_stub_manager(apt, obj);
if (!manager)
{
COM_ApartmentRelease(apt);
return E_OUTOFMEMORY;
}
mid->oid = manager->oid;
stdobjref->oid = manager->oid;
}
tablemarshal = ((mshlflags & MSHLFLAGS_TABLESTRONG) || (mshlflags & MSHLFLAGS_TABLEWEAK));
@ -142,22 +160,28 @@ static HRESULT register_ifstub(wine_marshal_id *mid, REFIID riid, IUnknown *obj,
ifstub = stub_manager_new_ifstub(manager, stub, obj, riid, tablemarshal);
if (!ifstub)
{
IRpcStubBuffer_Release(stub);
stub_manager_int_release(manager);
/* FIXME: should we do another release to completely destroy the
* stub manager? */
COM_ApartmentRelease(apt);
return E_OUTOFMEMORY;
}
if (!tablemarshal)
stub_manager_ext_addref(manager, 1);
else if (mshlflags & MSHLFLAGS_TABLESTRONG)
stub_manager_ext_addref(manager, 1);
{
stdobjref->cPublicRefs = NORMALEXTREFS;
stub_manager_ext_addref(manager, stdobjref->cPublicRefs);
}
else
{
stdobjref->cPublicRefs = 0;
if (mshlflags & MSHLFLAGS_TABLESTRONG)
stub_manager_ext_addref(manager, 1);
}
mid->ipid = ifstub->ipid;
stdobjref->ipid = ifstub->ipid;
stub_manager_int_release(manager);
COM_ApartmentRelease(apt);
return S_OK;
}
@ -557,10 +581,10 @@ StdMarshalImpl_GetUnmarshalClass(
static HRESULT WINAPI
StdMarshalImpl_GetMarshalSizeMax(
LPMARSHAL iface, REFIID riid, void* pv, DWORD dwDestContext,
void* pvDestContext, DWORD mshlflags, DWORD* pSize
) {
*pSize = sizeof(wine_marshal_id);
return S_OK;
void* pvDestContext, DWORD mshlflags, DWORD* pSize)
{
*pSize = sizeof(STDOBJREF);
return S_OK;
}
static HRESULT WINAPI
@ -568,12 +592,10 @@ StdMarshalImpl_MarshalInterface(
LPMARSHAL iface, IStream *pStm,REFIID riid, void* pv, DWORD dwDestContext,
void* pvDestContext, DWORD mshlflags
) {
wine_marshal_id mid;
STDOBJREF stdobjref;
IUnknown *pUnk;
ULONG res;
HRESULT hres;
IRpcStubBuffer *stubbuffer;
IPSFactoryBuffer *psfacbuf;
struct stub_manager *manager;
APARTMENT *apt = COM_CurrentApt();
@ -587,32 +609,19 @@ StdMarshalImpl_MarshalInterface(
start_apartment_listener_thread(); /* just to be sure we have one running. */
hres = get_facbuf_for_iid(riid,&psfacbuf);
if (hres) return hres;
hres = IPSFactoryBuffer_CreateStub(psfacbuf,riid,pv,&stubbuffer);
IPSFactoryBuffer_Release(psfacbuf);
if (hres) {
FIXME("Failed to create an RpcStubBuffer from PSFactory for %s\n",debugstr_guid(riid));
return hres;
}
/* now fill out the MID */
mid.oxid = apt->oxid;
IUnknown_QueryInterface((LPUNKNOWN)pv, riid, (LPVOID*)&pUnk);
if ((manager = get_stub_manager_from_object(apt, pUnk)))
{
mid.oid = manager->oid;
stdobjref.oid = manager->oid;
stub_manager_int_release(manager);
}
else
{
mid.oid = 0; /* will be set by register_ifstub */
stdobjref.oid = 0; /* will be set by register_ifstub */
}
hres = register_ifstub(&mid, riid, pUnk, stubbuffer, mshlflags);
hres = register_ifstub(apt, &stdobjref, riid, pUnk, mshlflags);
IUnknown_Release(pUnk);
@ -622,7 +631,7 @@ StdMarshalImpl_MarshalInterface(
return hres;
}
hres = IStream_Write(pStm,&mid,sizeof(mid),&res);
hres = IStream_Write(pStm, &stdobjref, sizeof(stdobjref), &res);
if (hres) return hres;
return S_OK;
@ -632,13 +641,12 @@ static HRESULT WINAPI
StdMarshalImpl_UnmarshalInterface(LPMARSHAL iface, IStream *pStm, REFIID riid, void **ppv)
{
struct stub_manager *stubmgr;
wine_marshal_id mid;
STDOBJREF stdobjref;
ULONG res;
HRESULT hres;
struct proxy_manager *proxy_manager = NULL;
APARTMENT *apt = COM_CurrentApt();
APARTMENT *stub_apt;
ULONG cPublicRefs = 1;
TRACE("(...,%s,....)\n",debugstr_guid(riid));
@ -648,18 +656,19 @@ StdMarshalImpl_UnmarshalInterface(LPMARSHAL iface, IStream *pStm, REFIID riid, v
return CO_E_NOTINITIALIZED;
}
hres = IStream_Read(pStm,&mid,sizeof(mid),&res);
hres = IStream_Read(pStm, &stdobjref, sizeof(stdobjref), &res);
if (hres) return hres;
/* check if we're marshalling back to ourselves */
if ((apt->oxid == mid.oxid) && (stubmgr = get_stub_manager(apt, mid.oid)))
if ((apt->oxid == stdobjref.oxid) && (stubmgr = get_stub_manager(apt, stdobjref.oid)))
{
TRACE("Unmarshalling object marshalled in same apartment for iid %s, returning original object %p\n", debugstr_guid(riid), stubmgr->object);
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, &mid.ipid))
if (!stub_manager_is_table_marshaled(stubmgr, &stdobjref.ipid))
stub_manager_ext_release(stubmgr, 1);
stub_manager_int_release(stubmgr);
@ -671,40 +680,44 @@ StdMarshalImpl_UnmarshalInterface(LPMARSHAL 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 = COM_ApartmentFromOXID(mid.oxid, TRUE)))
if ((stub_apt = COM_ApartmentFromOXID(stdobjref.oxid, TRUE)))
{
if ((stubmgr = get_stub_manager(stub_apt, mid.oid)))
if ((stubmgr = get_stub_manager(stub_apt, stdobjref.oid)))
{
if (!stub_manager_notify_unmarshal(stubmgr, &mid.ipid))
if (!stub_manager_notify_unmarshal(stubmgr, &stdobjref.ipid))
hres = CO_E_OBJNOTCONNECTED;
/* FIXME: hack around not using STDOBJREF yet */
if (stub_manager_is_table_marshaled(stubmgr, &mid.ipid))
cPublicRefs = 0;
stub_manager_int_release(stubmgr);
}
else
{
WARN("Couldn't find object for OXID %s, OID %s, assuming disconnected\n",
wine_dbgstr_longlong(mid.oxid),
wine_dbgstr_longlong(mid.oid));
wine_dbgstr_longlong(stdobjref.oxid),
wine_dbgstr_longlong(stdobjref.oid));
hres = CO_E_OBJNOTCONNECTED;
}
COM_ApartmentRelease(stub_apt);
}
else
TRACE("Treating unmarshal from OXID %s as inter-process\n", wine_dbgstr_longlong(mid.oxid));
TRACE("Treating unmarshal from OXID %s as inter-process\n",
wine_dbgstr_longlong(stdobjref.oxid));
if (hres) return hres;
if (!find_proxy_manager(apt, mid.oxid, mid.oid, &proxy_manager))
if (!find_proxy_manager(apt, stdobjref.oxid, stdobjref.oid, &proxy_manager))
{
IRpcChannelBuffer *chanbuf;
wine_marshal_id mid;
mid.oxid = stdobjref.oxid;
mid.oid = stdobjref.oid;
mid.ipid = stdobjref.ipid;
hres = PIPE_GetNewPipeBuf(&mid,&chanbuf);
if (hres == S_OK)
hres = proxy_manager_construct(apt, mid.oxid, mid.oid, chanbuf, &proxy_manager);
hres = proxy_manager_construct(apt, stdobjref.oxid, stdobjref.oid,
chanbuf, &proxy_manager);
}
if (hres == S_OK)
@ -722,8 +735,9 @@ StdMarshalImpl_UnmarshalInterface(LPMARSHAL iface, IStream *pStm, REFIID riid, v
struct ifproxy * ifproxy;
hres = proxy_manager_find_ifproxy(proxy_manager, riid, &ifproxy);
if (hres == E_NOINTERFACE)
hres = proxy_manager_create_ifproxy(proxy_manager, mid.ipid,
riid, cPublicRefs, &ifproxy);
hres = proxy_manager_create_ifproxy(proxy_manager, stdobjref.ipid,
riid, stdobjref.cPublicRefs,
&ifproxy);
if (hres == S_OK)
{
@ -744,7 +758,7 @@ StdMarshalImpl_UnmarshalInterface(LPMARSHAL iface, IStream *pStm, REFIID riid, v
static HRESULT WINAPI
StdMarshalImpl_ReleaseMarshalData(LPMARSHAL iface, IStream *pStm) {
wine_marshal_id mid;
STDOBJREF stdobjref;
ULONG res;
HRESULT hres;
struct stub_manager *stubmgr;
@ -752,22 +766,25 @@ StdMarshalImpl_ReleaseMarshalData(LPMARSHAL iface, IStream *pStm) {
TRACE("iface=%p, pStm=%p\n", iface, pStm);
hres = IStream_Read(pStm,&mid,sizeof(mid),&res);
hres = IStream_Read(pStm, &stdobjref, sizeof(stdobjref), &res);
if (hres) return hres;
if (!(apt = COM_ApartmentFromOXID(mid.oxid, TRUE)))
if (!(apt = COM_ApartmentFromOXID(stdobjref.oxid, TRUE)))
{
WARN("Could not map OXID %s to apartment object\n", wine_dbgstr_longlong(mid.oxid));
WARN("Could not map OXID %s to apartment object\n",
wine_dbgstr_longlong(stdobjref.oxid));
return RPC_E_INVALID_OBJREF;
}
if (!(stubmgr = get_stub_manager(apt, mid.oid)))
if (!(stubmgr = get_stub_manager(apt, stdobjref.oid)))
{
ERR("could not map MID to stub manager, oxid=%s, oid=%s\n",
wine_dbgstr_longlong(mid.oxid), wine_dbgstr_longlong(mid.oid));
wine_dbgstr_longlong(stdobjref.oxid), wine_dbgstr_longlong(stdobjref.oid));
return RPC_E_INVALID_OBJREF;
}
/* FIXME: don't release if table-weak and already unmarshaled an object */
/* FIXME: this should also depend on stdobjref.cPublicRefs */
stub_manager_ext_release(stubmgr, 1);
stub_manager_int_release(stubmgr);