Commit 527ef47d authored by Robert Shearman's avatar Robert Shearman Committed by Alexandre Julliard

Make each ifproxy have its own channel buffer to fix a bug where a

proxy with multiple interfaces could invoke the wrong stub buffer on the server.
parent ee5be579
......@@ -97,6 +97,7 @@ struct ifproxy
IPID ipid; /* imported interface ID (RO) */
LPRPCPROXYBUFFER proxy; /* interface proxy (RO) */
DWORD refs; /* imported (public) references (CS parent->cs) */
IRpcChannelBuffer *chan; /* channel to object (CS parent->cs) */
};
/* imported object / proxy manager */
......@@ -105,7 +106,6 @@ struct proxy_manager
const IMultiQIVtbl *lpVtbl;
struct apartment *parent; /* owning apartment (RO) */
struct list entry; /* entry in apartment (CS parent->cs) */
LPRPCCHANNELBUFFER chan; /* channel to object (CS cs) */
OXID oxid; /* object exported ID (RO) */
OID oid; /* object ID (RO) */
struct list interfaces; /* imported interfaces (CS cs) */
......
......@@ -377,12 +377,17 @@ static HRESULT ifproxy_release_public_refs(struct ifproxy * This)
return hr;
}
/* should be called inside This->parent->cs critical section */
static void ifproxy_disconnect(struct ifproxy * This)
{
ifproxy_release_public_refs(This);
if (This->proxy) IRpcProxyBuffer_Disconnect(This->proxy);
IRpcChannelBuffer_Release(This->chan);
This->chan = NULL;
}
/* should be called in This->parent->cs critical section if it is an entry in parent's list */
static void ifproxy_destroy(struct ifproxy * This)
{
TRACE("%p\n", This);
......@@ -393,6 +398,12 @@ static void ifproxy_destroy(struct ifproxy * This)
list_remove(&This->entry);
if (This->chan)
{
IRpcChannelBuffer_Release(This->chan);
This->chan = NULL;
}
/* note: we don't call Release for This->proxy because its lifetime is
* controlled by the return value from ClientIdentity_Release, which this
* function is always called from */
......@@ -402,7 +413,7 @@ static void ifproxy_destroy(struct ifproxy * This)
static HRESULT proxy_manager_construct(
APARTMENT * apt, ULONG sorflags, OXID oxid, OID oid,
IRpcChannelBuffer * channel, struct proxy_manager ** proxy_manager)
struct proxy_manager ** proxy_manager)
{
struct proxy_manager * This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
if (!This) return E_OUTOFMEMORY;
......@@ -428,9 +439,6 @@ static HRESULT proxy_manager_construct(
* should store the STDOBJREF flags in the proxy manager. */
This->sorflags = sorflags;
assert(channel);
This->chan = channel; /* FIXME: we should take the binding strings and construct the channel in this function */
/* we create the IRemUnknown proxy on demand */
This->remunk = NULL;
......@@ -479,7 +487,7 @@ static HRESULT proxy_manager_query_local_interface(struct proxy_manager * This,
static HRESULT proxy_manager_create_ifproxy(
struct proxy_manager * This, const IPID *ipid, REFIID riid, ULONG cPublicRefs,
struct ifproxy ** iif_out)
IRpcChannelBuffer * channel, struct ifproxy ** iif_out)
{
HRESULT hr;
IPSFactoryBuffer * psfb;
......@@ -494,6 +502,9 @@ static HRESULT proxy_manager_create_ifproxy(
ifproxy->refs = cPublicRefs;
ifproxy->proxy = NULL;
assert(channel);
ifproxy->chan = channel; /* FIXME: we should take the binding strings and construct the channel in this function */
/* the IUnknown interface is special because it does not have a
* proxy associated with the ifproxy as we handle IUnknown ourselves */
if (IsEqualIID(riid, &IID_IUnknown))
......@@ -522,7 +533,7 @@ static HRESULT proxy_manager_create_ifproxy(
debugstr_guid(riid), hr);
if (hr == S_OK)
hr = IRpcProxyBuffer_Connect(ifproxy->proxy, This->chan);
hr = IRpcProxyBuffer_Connect(ifproxy->proxy, ifproxy->chan);
}
/* get at least one external reference to the object to keep it alive */
......@@ -584,11 +595,6 @@ static void proxy_manager_disconnect(struct proxy_manager * This)
/* apartment is being destroyed so don't keep a pointer around to it */
This->parent = NULL;
/* FIXME: will this still be necessary if/when we use a real RPC
* channel? */
IRpcChannelBuffer_Release(This->chan);
This->chan = NULL;
LeaveCriticalSection(&This->cs);
}
......@@ -676,7 +682,6 @@ static void proxy_manager_destroy(struct proxy_manager * This)
}
if (This->remunk) IRemUnknown_Release(This->remunk);
if (This->chan) IRpcChannelBuffer_Release(This->chan);
DeleteCriticalSection(&This->cs);
......@@ -844,13 +849,9 @@ static HRESULT unmarshal_object(const STDOBJREF *stdobjref, APARTMENT *apt, REFI
* object */
if (!find_proxy_manager(apt, stdobjref->oxid, stdobjref->oid, &proxy_manager))
{
IRpcChannelBuffer *chanbuf;
hr = RPC_CreateClientChannel(&stdobjref->oxid, &stdobjref->ipid, &chanbuf);
if (hr == S_OK)
hr = proxy_manager_construct(apt, stdobjref->flags,
stdobjref->oxid, stdobjref->oid,
chanbuf, &proxy_manager);
hr = proxy_manager_construct(apt, stdobjref->flags,
stdobjref->oxid, stdobjref->oid,
&proxy_manager);
}
else
TRACE("proxy manager already created, using\n");
......@@ -860,9 +861,14 @@ static HRESULT unmarshal_object(const STDOBJREF *stdobjref, APARTMENT *apt, REFI
struct ifproxy * ifproxy;
hr = proxy_manager_find_ifproxy(proxy_manager, riid, &ifproxy);
if (hr == E_NOINTERFACE)
hr = proxy_manager_create_ifproxy(proxy_manager, &stdobjref->ipid,
riid, stdobjref->cPublicRefs,
&ifproxy);
{
IRpcChannelBuffer *chanbuf;
hr = RPC_CreateClientChannel(&stdobjref->oxid, &stdobjref->ipid, &chanbuf);
if (hr == S_OK)
hr = proxy_manager_create_ifproxy(proxy_manager, &stdobjref->ipid,
riid, stdobjref->cPublicRefs,
chanbuf, &ifproxy);
}
if (hr == S_OK)
{
......
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