Give IUnknown its own ifstub to fix ref-counting and ipid storage
issues.
This commit is contained in:
parent
da8b3dd7f2
commit
5bef770490
|
@ -375,7 +375,7 @@ static HRESULT ifproxy_release_public_refs(struct ifproxy * This)
|
||||||
static void ifproxy_disconnect(struct ifproxy * This)
|
static void ifproxy_disconnect(struct ifproxy * This)
|
||||||
{
|
{
|
||||||
ifproxy_release_public_refs(This);
|
ifproxy_release_public_refs(This);
|
||||||
IRpcProxyBuffer_Disconnect(This->proxy);
|
if (This->proxy) IRpcProxyBuffer_Disconnect(This->proxy);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ifproxy_destroy(struct ifproxy * This)
|
static void ifproxy_destroy(struct ifproxy * This)
|
||||||
|
@ -483,26 +483,36 @@ static HRESULT proxy_manager_create_ifproxy(
|
||||||
ifproxy->refs = cPublicRefs;
|
ifproxy->refs = cPublicRefs;
|
||||||
ifproxy->proxy = NULL;
|
ifproxy->proxy = NULL;
|
||||||
|
|
||||||
hr = get_facbuf_for_iid(riid, &psfb);
|
/* the IUnknown interface is special because it does not have a
|
||||||
if (hr == S_OK)
|
* proxy associated with the ifproxy as we handle IUnknown ourselves */
|
||||||
|
if (IsEqualIID(riid, &IID_IUnknown))
|
||||||
{
|
{
|
||||||
/* important note: the outer unknown is set to the proxy manager.
|
ifproxy->iface = (void *)&This->lpVtbl;
|
||||||
* This ensures the COM identity rules are not violated, by having a
|
hr = S_OK;
|
||||||
* one-to-one mapping of objects on the proxy side to objects on the
|
|
||||||
* stub side, no matter which interface you view the object through */
|
|
||||||
hr = IPSFactoryBuffer_CreateProxy(psfb, (IUnknown *)&This->lpVtbl, riid,
|
|
||||||
&ifproxy->proxy, &ifproxy->iface);
|
|
||||||
IPSFactoryBuffer_Release(psfb);
|
|
||||||
if (hr != S_OK)
|
|
||||||
ERR("Could not create proxy for interface %s, error 0x%08lx\n",
|
|
||||||
debugstr_guid(riid), hr);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
ERR("Could not get IPSFactoryBuffer for interface %s, error 0x%08lx\n",
|
{
|
||||||
debugstr_guid(riid), hr);
|
hr = get_facbuf_for_iid(riid, &psfb);
|
||||||
|
if (hr == S_OK)
|
||||||
|
{
|
||||||
|
/* important note: the outer unknown is set to the proxy manager.
|
||||||
|
* This ensures the COM identity rules are not violated, by having a
|
||||||
|
* one-to-one mapping of objects on the proxy side to objects on the
|
||||||
|
* stub side, no matter which interface you view the object through */
|
||||||
|
hr = IPSFactoryBuffer_CreateProxy(psfb, (IUnknown *)&This->lpVtbl, riid,
|
||||||
|
&ifproxy->proxy, &ifproxy->iface);
|
||||||
|
IPSFactoryBuffer_Release(psfb);
|
||||||
|
if (hr != S_OK)
|
||||||
|
ERR("Could not create proxy for interface %s, error 0x%08lx\n",
|
||||||
|
debugstr_guid(riid), hr);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
ERR("Could not get IPSFactoryBuffer for interface %s, error 0x%08lx\n",
|
||||||
|
debugstr_guid(riid), hr);
|
||||||
|
|
||||||
if (hr == S_OK)
|
if (hr == S_OK)
|
||||||
hr = IRpcProxyBuffer_Connect(ifproxy->proxy, This->chan);
|
hr = IRpcProxyBuffer_Connect(ifproxy->proxy, This->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 */
|
||||||
if (hr == S_OK)
|
if (hr == S_OK)
|
||||||
|
@ -844,29 +854,18 @@ static HRESULT unmarshal_object(const STDOBJREF *stdobjref, APARTMENT *apt, REFI
|
||||||
|
|
||||||
if (hr == S_OK)
|
if (hr == S_OK)
|
||||||
{
|
{
|
||||||
/* the IUnknown interface is special because it does not have an
|
struct ifproxy * ifproxy;
|
||||||
* ifproxy associated with it. we simply return the controlling
|
hr = proxy_manager_find_ifproxy(proxy_manager, riid, &ifproxy);
|
||||||
* IUnknown of the proxy manager. */
|
if (hr == E_NOINTERFACE)
|
||||||
if (IsEqualIID(riid, &IID_IUnknown))
|
hr = proxy_manager_create_ifproxy(proxy_manager, stdobjref->ipid,
|
||||||
{
|
riid, stdobjref->cPublicRefs,
|
||||||
ClientIdentity_AddRef((IMultiQI*)&proxy_manager->lpVtbl);
|
&ifproxy);
|
||||||
*object = (LPVOID)(&proxy_manager->lpVtbl);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
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);
|
|
||||||
|
|
||||||
if (hr == S_OK)
|
if (hr == S_OK)
|
||||||
{
|
{
|
||||||
/* FIXME: push this AddRef inside proxy_manager_find_ifproxy/create_ifproxy? */
|
/* FIXME: push this AddRef inside proxy_manager_find_ifproxy/create_ifproxy? */
|
||||||
ClientIdentity_AddRef((IMultiQI*)&proxy_manager->lpVtbl);
|
ClientIdentity_AddRef((IMultiQI*)&proxy_manager->lpVtbl);
|
||||||
*object = ifproxy->iface;
|
*object = ifproxy->iface;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -803,9 +803,7 @@ static void test_message_filter()
|
||||||
|
|
||||||
IClassFactory_Release(cf);
|
IClassFactory_Release(cf);
|
||||||
|
|
||||||
/* FIXME: this is a regression caused by the fact that I faked the
|
ok_no_locks();
|
||||||
* IUnknown unmarshaling too much and didn't give it its own ifstub. */
|
|
||||||
todo_wine { ok_no_locks(); }
|
|
||||||
|
|
||||||
end_host_object(tid, thread);
|
end_host_object(tid, thread);
|
||||||
}
|
}
|
||||||
|
@ -861,7 +859,7 @@ static void test_proxy_interfaces()
|
||||||
ok_more_than_one_lock();
|
ok_more_than_one_lock();
|
||||||
|
|
||||||
IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
|
IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
|
||||||
hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
|
hr = CoUnmarshalInterface(pStream, &IID_IUnknown, (void **)&pProxy);
|
||||||
ok_ole_success(hr, CoReleaseMarshalData);
|
ok_ole_success(hr, CoReleaseMarshalData);
|
||||||
IStream_Release(pStream);
|
IStream_Release(pStream);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue