Give IUnknown its own ifstub to fix ref-counting and ipid storage

issues.
This commit is contained in:
Robert Shearman 2005-01-27 10:39:44 +00:00 committed by Alexandre Julliard
parent da8b3dd7f2
commit 5bef770490
2 changed files with 40 additions and 43 deletions

View File

@ -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;
}
} }
} }

View File

@ -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);