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.
This commit is contained in:
parent
ee5be57935
commit
527ef47d70
|
@ -97,6 +97,7 @@ struct ifproxy
|
||||||
IPID ipid; /* imported interface ID (RO) */
|
IPID ipid; /* imported interface ID (RO) */
|
||||||
LPRPCPROXYBUFFER proxy; /* interface proxy (RO) */
|
LPRPCPROXYBUFFER proxy; /* interface proxy (RO) */
|
||||||
DWORD refs; /* imported (public) references (CS parent->cs) */
|
DWORD refs; /* imported (public) references (CS parent->cs) */
|
||||||
|
IRpcChannelBuffer *chan; /* channel to object (CS parent->cs) */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* imported object / proxy manager */
|
/* imported object / proxy manager */
|
||||||
|
@ -105,7 +106,6 @@ struct proxy_manager
|
||||||
const IMultiQIVtbl *lpVtbl;
|
const IMultiQIVtbl *lpVtbl;
|
||||||
struct apartment *parent; /* owning apartment (RO) */
|
struct apartment *parent; /* owning apartment (RO) */
|
||||||
struct list entry; /* entry in apartment (CS parent->cs) */
|
struct list entry; /* entry in apartment (CS parent->cs) */
|
||||||
LPRPCCHANNELBUFFER chan; /* channel to object (CS cs) */
|
|
||||||
OXID oxid; /* object exported ID (RO) */
|
OXID oxid; /* object exported ID (RO) */
|
||||||
OID oid; /* object ID (RO) */
|
OID oid; /* object ID (RO) */
|
||||||
struct list interfaces; /* imported interfaces (CS cs) */
|
struct list interfaces; /* imported interfaces (CS cs) */
|
||||||
|
|
|
@ -377,12 +377,17 @@ static HRESULT ifproxy_release_public_refs(struct ifproxy * This)
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* should be called inside This->parent->cs critical section */
|
||||||
static void ifproxy_disconnect(struct ifproxy * This)
|
static void ifproxy_disconnect(struct ifproxy * This)
|
||||||
{
|
{
|
||||||
ifproxy_release_public_refs(This);
|
ifproxy_release_public_refs(This);
|
||||||
if (This->proxy) IRpcProxyBuffer_Disconnect(This->proxy);
|
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)
|
static void ifproxy_destroy(struct ifproxy * This)
|
||||||
{
|
{
|
||||||
TRACE("%p\n", This);
|
TRACE("%p\n", This);
|
||||||
|
@ -393,6 +398,12 @@ static void ifproxy_destroy(struct ifproxy * This)
|
||||||
|
|
||||||
list_remove(&This->entry);
|
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
|
/* note: we don't call Release for This->proxy because its lifetime is
|
||||||
* controlled by the return value from ClientIdentity_Release, which this
|
* controlled by the return value from ClientIdentity_Release, which this
|
||||||
* function is always called from */
|
* function is always called from */
|
||||||
|
@ -402,7 +413,7 @@ static void ifproxy_destroy(struct ifproxy * This)
|
||||||
|
|
||||||
static HRESULT proxy_manager_construct(
|
static HRESULT proxy_manager_construct(
|
||||||
APARTMENT * apt, ULONG sorflags, OXID oxid, OID oid,
|
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));
|
struct proxy_manager * This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
|
||||||
if (!This) return E_OUTOFMEMORY;
|
if (!This) return E_OUTOFMEMORY;
|
||||||
|
@ -428,9 +439,6 @@ static HRESULT proxy_manager_construct(
|
||||||
* should store the STDOBJREF flags in the proxy manager. */
|
* should store the STDOBJREF flags in the proxy manager. */
|
||||||
This->sorflags = sorflags;
|
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 */
|
/* we create the IRemUnknown proxy on demand */
|
||||||
This->remunk = NULL;
|
This->remunk = NULL;
|
||||||
|
|
||||||
|
@ -479,7 +487,7 @@ static HRESULT proxy_manager_query_local_interface(struct proxy_manager * This,
|
||||||
|
|
||||||
static HRESULT proxy_manager_create_ifproxy(
|
static HRESULT proxy_manager_create_ifproxy(
|
||||||
struct proxy_manager * This, const IPID *ipid, REFIID riid, ULONG cPublicRefs,
|
struct proxy_manager * This, const IPID *ipid, REFIID riid, ULONG cPublicRefs,
|
||||||
struct ifproxy ** iif_out)
|
IRpcChannelBuffer * channel, struct ifproxy ** iif_out)
|
||||||
{
|
{
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
IPSFactoryBuffer * psfb;
|
IPSFactoryBuffer * psfb;
|
||||||
|
@ -494,6 +502,9 @@ static HRESULT proxy_manager_create_ifproxy(
|
||||||
ifproxy->refs = cPublicRefs;
|
ifproxy->refs = cPublicRefs;
|
||||||
ifproxy->proxy = NULL;
|
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
|
/* the IUnknown interface is special because it does not have a
|
||||||
* proxy associated with the ifproxy as we handle IUnknown ourselves */
|
* proxy associated with the ifproxy as we handle IUnknown ourselves */
|
||||||
if (IsEqualIID(riid, &IID_IUnknown))
|
if (IsEqualIID(riid, &IID_IUnknown))
|
||||||
|
@ -522,7 +533,7 @@ static HRESULT proxy_manager_create_ifproxy(
|
||||||
debugstr_guid(riid), hr);
|
debugstr_guid(riid), hr);
|
||||||
|
|
||||||
if (hr == S_OK)
|
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 */
|
/* 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 */
|
/* apartment is being destroyed so don't keep a pointer around to it */
|
||||||
This->parent = NULL;
|
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);
|
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->remunk) IRemUnknown_Release(This->remunk);
|
||||||
if (This->chan) IRpcChannelBuffer_Release(This->chan);
|
|
||||||
|
|
||||||
DeleteCriticalSection(&This->cs);
|
DeleteCriticalSection(&This->cs);
|
||||||
|
|
||||||
|
@ -844,13 +849,9 @@ static HRESULT unmarshal_object(const STDOBJREF *stdobjref, APARTMENT *apt, REFI
|
||||||
* object */
|
* object */
|
||||||
if (!find_proxy_manager(apt, stdobjref->oxid, stdobjref->oid, &proxy_manager))
|
if (!find_proxy_manager(apt, stdobjref->oxid, stdobjref->oid, &proxy_manager))
|
||||||
{
|
{
|
||||||
IRpcChannelBuffer *chanbuf;
|
hr = proxy_manager_construct(apt, stdobjref->flags,
|
||||||
|
stdobjref->oxid, stdobjref->oid,
|
||||||
hr = RPC_CreateClientChannel(&stdobjref->oxid, &stdobjref->ipid, &chanbuf);
|
&proxy_manager);
|
||||||
if (hr == S_OK)
|
|
||||||
hr = proxy_manager_construct(apt, stdobjref->flags,
|
|
||||||
stdobjref->oxid, stdobjref->oid,
|
|
||||||
chanbuf, &proxy_manager);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
TRACE("proxy manager already created, using\n");
|
TRACE("proxy manager already created, using\n");
|
||||||
|
@ -860,9 +861,14 @@ static HRESULT unmarshal_object(const STDOBJREF *stdobjref, APARTMENT *apt, REFI
|
||||||
struct ifproxy * ifproxy;
|
struct ifproxy * ifproxy;
|
||||||
hr = proxy_manager_find_ifproxy(proxy_manager, riid, &ifproxy);
|
hr = proxy_manager_find_ifproxy(proxy_manager, riid, &ifproxy);
|
||||||
if (hr == E_NOINTERFACE)
|
if (hr == E_NOINTERFACE)
|
||||||
hr = proxy_manager_create_ifproxy(proxy_manager, &stdobjref->ipid,
|
{
|
||||||
riid, stdobjref->cPublicRefs,
|
IRpcChannelBuffer *chanbuf;
|
||||||
&ifproxy);
|
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)
|
if (hr == S_OK)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue