- The apartment reference should be held while the stub manager
reference is held. - Fix same apartment-unmarshal detection.
This commit is contained in:
parent
3bc9380619
commit
6036a773e2
|
@ -183,8 +183,8 @@ ULONG stub_manager_ext_addref(struct stub_manager *m, ULONG refs);
|
||||||
ULONG stub_manager_ext_release(struct stub_manager *m, ULONG refs);
|
ULONG stub_manager_ext_release(struct stub_manager *m, ULONG refs);
|
||||||
IRpcStubBuffer *stub_manager_ipid_to_stubbuffer(struct stub_manager *m, const IPID *iid);
|
IRpcStubBuffer *stub_manager_ipid_to_stubbuffer(struct stub_manager *m, const IPID *iid);
|
||||||
struct ifstub *stub_manager_new_ifstub(struct stub_manager *m, IRpcStubBuffer *sb, IUnknown *iptr, REFIID iid, BOOL tablemarshal);
|
struct ifstub *stub_manager_new_ifstub(struct stub_manager *m, IRpcStubBuffer *sb, IUnknown *iptr, REFIID iid, BOOL tablemarshal);
|
||||||
struct stub_manager *get_stub_manager(OXID oxid, OID oid);
|
struct stub_manager *get_stub_manager(APARTMENT *apt, OID oid);
|
||||||
struct stub_manager *get_stub_manager_from_object(OXID oxid, void *object);
|
struct stub_manager *get_stub_manager_from_object(APARTMENT *apt, void *object);
|
||||||
|
|
||||||
IRpcStubBuffer *mid_to_stubbuffer(wine_marshal_id *mid);
|
IRpcStubBuffer *mid_to_stubbuffer(wine_marshal_id *mid);
|
||||||
|
|
||||||
|
|
|
@ -79,9 +79,16 @@ get_facbuf_for_iid(REFIID riid,IPSFactoryBuffer **facbuf) {
|
||||||
IRpcStubBuffer *mid_to_stubbuffer(wine_marshal_id *mid)
|
IRpcStubBuffer *mid_to_stubbuffer(wine_marshal_id *mid)
|
||||||
{
|
{
|
||||||
IRpcStubBuffer *ret;
|
IRpcStubBuffer *ret;
|
||||||
|
APARTMENT *apt;
|
||||||
struct stub_manager *m;
|
struct stub_manager *m;
|
||||||
|
|
||||||
if (!(m = get_stub_manager(mid->oxid, mid->oid)))
|
if (!(apt = COM_ApartmentFromOXID(mid->oxid, TRUE)))
|
||||||
|
{
|
||||||
|
WARN("Could not map OXID %s to apartment object\n", wine_dbgstr_longlong(mid->oxid));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(m = get_stub_manager(apt, mid->oid)))
|
||||||
{
|
{
|
||||||
WARN("unknown OID %s\n", wine_dbgstr_longlong(mid->oid));
|
WARN("unknown OID %s\n", wine_dbgstr_longlong(mid->oid));
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -90,6 +97,9 @@ IRpcStubBuffer *mid_to_stubbuffer(wine_marshal_id *mid)
|
||||||
ret = stub_manager_ipid_to_stubbuffer(m, &mid->ipid);
|
ret = stub_manager_ipid_to_stubbuffer(m, &mid->ipid);
|
||||||
|
|
||||||
stub_manager_int_release(m);
|
stub_manager_int_release(m);
|
||||||
|
|
||||||
|
COM_ApartmentRelease(apt);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,23 +108,30 @@ static HRESULT register_ifstub(wine_marshal_id *mid, REFIID riid, IUnknown *obj,
|
||||||
{
|
{
|
||||||
struct stub_manager *manager = NULL;
|
struct stub_manager *manager = NULL;
|
||||||
struct ifstub *ifstub;
|
struct ifstub *ifstub;
|
||||||
|
APARTMENT *apt;
|
||||||
|
|
||||||
|
if (!(apt = COM_ApartmentFromOXID(mid->oxid, TRUE)))
|
||||||
|
{
|
||||||
|
ERR("Could not map OXID %s to apartment object\n", wine_dbgstr_longlong(mid->oxid));
|
||||||
|
return E_UNEXPECTED;
|
||||||
|
}
|
||||||
|
|
||||||
/* mid->oid of zero means create a new stub manager */
|
/* mid->oid of zero means create a new stub manager */
|
||||||
|
|
||||||
if (mid->oid && (manager = get_stub_manager(mid->oxid, mid->oid)))
|
if (mid->oid && (manager = get_stub_manager(apt, mid->oid)))
|
||||||
{
|
{
|
||||||
TRACE("registering new ifstub on pre-existing manager\n");
|
TRACE("registering new ifstub on pre-existing manager\n");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
struct apartment *apt;
|
|
||||||
|
|
||||||
TRACE("constructing new stub manager\n");
|
TRACE("constructing new stub manager\n");
|
||||||
|
|
||||||
apt = COM_ApartmentFromOXID(mid->oxid, TRUE);
|
|
||||||
manager = new_stub_manager(apt, obj);
|
manager = new_stub_manager(apt, obj);
|
||||||
COM_ApartmentRelease(apt);
|
if (!manager)
|
||||||
if (!manager) return E_OUTOFMEMORY;
|
{
|
||||||
|
COM_ApartmentRelease(apt);
|
||||||
|
return E_OUTOFMEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
mid->oid = manager->oid;
|
mid->oid = manager->oid;
|
||||||
}
|
}
|
||||||
|
@ -125,6 +142,7 @@ static HRESULT register_ifstub(wine_marshal_id *mid, REFIID riid, IUnknown *obj,
|
||||||
stub_manager_int_release(manager);
|
stub_manager_int_release(manager);
|
||||||
/* FIXME: should we do another release to completely destroy the
|
/* FIXME: should we do another release to completely destroy the
|
||||||
* stub manager? */
|
* stub manager? */
|
||||||
|
COM_ApartmentRelease(apt);
|
||||||
return E_OUTOFMEMORY;
|
return E_OUTOFMEMORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -133,6 +151,7 @@ static HRESULT register_ifstub(wine_marshal_id *mid, REFIID riid, IUnknown *obj,
|
||||||
mid->ipid = ifstub->ipid;
|
mid->ipid = ifstub->ipid;
|
||||||
|
|
||||||
stub_manager_int_release(manager);
|
stub_manager_int_release(manager);
|
||||||
|
COM_ApartmentRelease(apt);
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -489,9 +508,16 @@ StdMarshalImpl_MarshalInterface(
|
||||||
IPSFactoryBuffer *psfacbuf;
|
IPSFactoryBuffer *psfacbuf;
|
||||||
BOOL tablemarshal;
|
BOOL tablemarshal;
|
||||||
struct stub_manager *manager;
|
struct stub_manager *manager;
|
||||||
|
APARTMENT *apt = COM_CurrentApt();
|
||||||
|
|
||||||
TRACE("(...,%s,...)\n",debugstr_guid(riid));
|
TRACE("(...,%s,...)\n",debugstr_guid(riid));
|
||||||
|
|
||||||
|
if (!apt)
|
||||||
|
{
|
||||||
|
ERR("Apartment not initialized\n");
|
||||||
|
return CO_E_NOTINITIALIZED;
|
||||||
|
}
|
||||||
|
|
||||||
start_apartment_listener_thread(); /* just to be sure we have one running. */
|
start_apartment_listener_thread(); /* just to be sure we have one running. */
|
||||||
|
|
||||||
hres = get_facbuf_for_iid(riid,&psfacbuf);
|
hres = get_facbuf_for_iid(riid,&psfacbuf);
|
||||||
|
@ -508,11 +534,11 @@ StdMarshalImpl_MarshalInterface(
|
||||||
if (tablemarshal) FIXME("table marshalling unimplemented\n");
|
if (tablemarshal) FIXME("table marshalling unimplemented\n");
|
||||||
|
|
||||||
/* now fill out the MID */
|
/* now fill out the MID */
|
||||||
mid.oxid = COM_CurrentApt()->oxid;
|
mid.oxid = apt->oxid;
|
||||||
|
|
||||||
IUnknown_QueryInterface((LPUNKNOWN)pv, riid, (LPVOID*)&pUnk);
|
IUnknown_QueryInterface((LPUNKNOWN)pv, riid, (LPVOID*)&pUnk);
|
||||||
|
|
||||||
if ((manager = get_stub_manager_from_object(mid.oxid, pUnk)))
|
if ((manager = get_stub_manager_from_object(apt, pUnk)))
|
||||||
{
|
{
|
||||||
mid.oid = manager->oid;
|
mid.oid = manager->oid;
|
||||||
stub_manager_int_release(manager);
|
stub_manager_int_release(manager);
|
||||||
|
@ -551,14 +577,17 @@ StdMarshalImpl_UnmarshalInterface(LPMARSHAL iface, IStream *pStm, REFIID riid, v
|
||||||
|
|
||||||
TRACE("(...,%s,....)\n",debugstr_guid(riid));
|
TRACE("(...,%s,....)\n",debugstr_guid(riid));
|
||||||
|
|
||||||
if (!apt) return CO_E_NOTINITIALIZED;
|
if (!apt)
|
||||||
|
{
|
||||||
|
ERR("Apartment not initialized\n");
|
||||||
|
return CO_E_NOTINITIALIZED;
|
||||||
|
}
|
||||||
|
|
||||||
hres = IStream_Read(pStm,&mid,sizeof(mid),&res);
|
hres = IStream_Read(pStm,&mid,sizeof(mid),&res);
|
||||||
if (hres) return hres;
|
if (hres) return hres;
|
||||||
|
|
||||||
/* check if we're marshalling back to ourselves */
|
/* check if we're marshalling back to ourselves */
|
||||||
/* FIXME: commented out until we can get the tests passing with it uncommented. */
|
if ((apt->oxid == mid.oxid) && (stubmgr = get_stub_manager(apt, mid.oid)))
|
||||||
if (/*(apt->oxid == mid.oxid) &&*/ (stubmgr = get_stub_manager(mid.oxid, mid.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);
|
||||||
|
|
||||||
|
@ -600,13 +629,20 @@ StdMarshalImpl_ReleaseMarshalData(LPMARSHAL iface, IStream *pStm) {
|
||||||
ULONG res;
|
ULONG res;
|
||||||
HRESULT hres;
|
HRESULT hres;
|
||||||
struct stub_manager *stubmgr;
|
struct stub_manager *stubmgr;
|
||||||
|
APARTMENT *apt;
|
||||||
|
|
||||||
TRACE("iface=%p, pStm=%p\n", iface, pStm);
|
TRACE("iface=%p, pStm=%p\n", iface, pStm);
|
||||||
|
|
||||||
hres = IStream_Read(pStm,&mid,sizeof(mid),&res);
|
hres = IStream_Read(pStm,&mid,sizeof(mid),&res);
|
||||||
if (hres) return hres;
|
if (hres) return hres;
|
||||||
|
|
||||||
if (!(stubmgr = get_stub_manager(mid.oxid, mid.oid)))
|
if (!(apt = COM_ApartmentFromOXID(mid.oxid, TRUE)))
|
||||||
|
{
|
||||||
|
WARN("Could not map OXID %s to apartment object\n", wine_dbgstr_longlong(mid.oxid));
|
||||||
|
return RPC_E_INVALID_OBJREF;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(stubmgr = get_stub_manager(apt, mid.oid)))
|
||||||
{
|
{
|
||||||
ERR("could not map MID to stub manager, oxid=%s, oid=%s\n",
|
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(mid.oxid), wine_dbgstr_longlong(mid.oid));
|
||||||
|
@ -616,6 +652,7 @@ StdMarshalImpl_ReleaseMarshalData(LPMARSHAL iface, IStream *pStm) {
|
||||||
stub_manager_ext_release(stubmgr, 1);
|
stub_manager_ext_release(stubmgr, 1);
|
||||||
|
|
||||||
stub_manager_int_release(stubmgr);
|
stub_manager_int_release(stubmgr);
|
||||||
|
COM_ApartmentRelease(apt);
|
||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
|
@ -789,6 +789,7 @@ COM_RpcReceive(wine_pipe *xpipe) {
|
||||||
wine_rpc_disconnect_header header;
|
wine_rpc_disconnect_header header;
|
||||||
struct stub_manager *stubmgr;
|
struct stub_manager *stubmgr;
|
||||||
DWORD magic = 0xcafebabe;
|
DWORD magic = 0xcafebabe;
|
||||||
|
APARTMENT *apt;
|
||||||
|
|
||||||
hres = read_pipe(xhPipe, &header, sizeof(header));
|
hres = read_pipe(xhPipe, &header, sizeof(header));
|
||||||
if (hres) {
|
if (hres) {
|
||||||
|
@ -798,15 +799,23 @@ COM_RpcReceive(wine_pipe *xpipe) {
|
||||||
|
|
||||||
TRACE("read disconnect header\n");
|
TRACE("read disconnect header\n");
|
||||||
|
|
||||||
if (!(stubmgr = get_stub_manager(header.mid.oxid, header.mid.oid)))
|
if (!(apt = COM_ApartmentFromOXID(header.mid.oxid, TRUE)))
|
||||||
|
{
|
||||||
|
ERR("Could not map OXID %s to apartment object in disconnect\n", wine_dbgstr_longlong(header.mid.oxid));
|
||||||
|
goto disconnect_end;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(stubmgr = get_stub_manager(apt, header.mid.oid)))
|
||||||
{
|
{
|
||||||
ERR("could not locate stub to disconnect, mid.oid=%s\n", wine_dbgstr_longlong(header.mid.oid));
|
ERR("could not locate stub to disconnect, mid.oid=%s\n", wine_dbgstr_longlong(header.mid.oid));
|
||||||
|
COM_ApartmentRelease(apt);
|
||||||
goto disconnect_end;
|
goto disconnect_end;
|
||||||
}
|
}
|
||||||
|
|
||||||
stub_manager_ext_release(stubmgr, 1);
|
stub_manager_ext_release(stubmgr, 1);
|
||||||
|
|
||||||
stub_manager_int_release(stubmgr);
|
stub_manager_int_release(stubmgr);
|
||||||
|
COM_ApartmentRelease(apt);
|
||||||
|
|
||||||
disconnect_end:
|
disconnect_end:
|
||||||
write_pipe(xhPipe, &magic, sizeof(magic));
|
write_pipe(xhPipe, &magic, sizeof(magic));
|
||||||
|
|
|
@ -107,19 +107,13 @@ static void stub_manager_delete(struct stub_manager *m)
|
||||||
HeapFree(GetProcessHeap(), 0, m);
|
HeapFree(GetProcessHeap(), 0, m);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* gets the stub manager associated with an object - caller must call
|
/* gets the stub manager associated with an object - caller must have
|
||||||
* release on the stub manager when it is no longer needed */
|
* a reference to the apartment while a reference to the stub manager is held.
|
||||||
struct stub_manager *get_stub_manager_from_object(OXID oxid, void *object)
|
* it must also call release on the stub manager when it is no longer needed */
|
||||||
|
struct stub_manager *get_stub_manager_from_object(APARTMENT *apt, void *object)
|
||||||
{
|
{
|
||||||
struct stub_manager *result = NULL;
|
struct stub_manager *result = NULL;
|
||||||
struct list *cursor;
|
struct list *cursor;
|
||||||
APARTMENT *apt;
|
|
||||||
|
|
||||||
if (!(apt = COM_ApartmentFromOXID(oxid, TRUE)))
|
|
||||||
{
|
|
||||||
WARN("Could not map OXID %s to apartment object\n", wine_dbgstr_longlong(oxid));
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
EnterCriticalSection(&apt->cs);
|
EnterCriticalSection(&apt->cs);
|
||||||
LIST_FOR_EACH( cursor, &apt->stubmgrs )
|
LIST_FOR_EACH( cursor, &apt->stubmgrs )
|
||||||
|
@ -135,13 +129,44 @@ struct stub_manager *get_stub_manager_from_object(OXID oxid, void *object)
|
||||||
}
|
}
|
||||||
LeaveCriticalSection(&apt->cs);
|
LeaveCriticalSection(&apt->cs);
|
||||||
|
|
||||||
COM_ApartmentRelease(apt);
|
if (result)
|
||||||
|
TRACE("found %p for object %p\n", result, object);
|
||||||
TRACE("found %p from object %p\n", result, object);
|
else
|
||||||
|
TRACE("not found for object %p\n", object);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* gets the stub manager associated with an object id - caller must have
|
||||||
|
* a reference to the apartment while a reference to the stub manager is held.
|
||||||
|
* it must also call release on the stub manager when it is no longer needed */
|
||||||
|
struct stub_manager *get_stub_manager(APARTMENT *apt, OID oid)
|
||||||
|
{
|
||||||
|
struct stub_manager *result = NULL;
|
||||||
|
struct list *cursor;
|
||||||
|
|
||||||
|
EnterCriticalSection(&apt->cs);
|
||||||
|
LIST_FOR_EACH( cursor, &apt->stubmgrs )
|
||||||
|
{
|
||||||
|
struct stub_manager *m = LIST_ENTRY( cursor, struct stub_manager, entry );
|
||||||
|
|
||||||
|
if (m->oid == oid)
|
||||||
|
{
|
||||||
|
result = m;
|
||||||
|
stub_manager_int_addref(result);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LeaveCriticalSection(&apt->cs);
|
||||||
|
|
||||||
|
if (result)
|
||||||
|
TRACE("found %p for oid %s\n", result, wine_dbgstr_longlong(oid));
|
||||||
|
else
|
||||||
|
TRACE("not found for oid %s\n", wine_dbgstr_longlong(oid));
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/* increments the internal refcount */
|
/* increments the internal refcount */
|
||||||
ULONG stub_manager_int_addref(struct stub_manager *This)
|
ULONG stub_manager_int_addref(struct stub_manager *This)
|
||||||
{
|
{
|
||||||
|
@ -174,41 +199,6 @@ ULONG stub_manager_int_release(struct stub_manager *This)
|
||||||
return refs;
|
return refs;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* gets the stub manager associated with an object id - caller must call
|
|
||||||
* release on the stub manager when it is no longer needed */
|
|
||||||
struct stub_manager *get_stub_manager(OXID oxid, OID oid)
|
|
||||||
{
|
|
||||||
struct stub_manager *result = NULL;
|
|
||||||
struct list *cursor;
|
|
||||||
APARTMENT *apt;
|
|
||||||
|
|
||||||
if (!(apt = COM_ApartmentFromOXID(oxid, TRUE)))
|
|
||||||
{
|
|
||||||
WARN("Could not map OXID %s to apartment object\n", wine_dbgstr_longlong(oxid));
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
EnterCriticalSection(&apt->cs);
|
|
||||||
LIST_FOR_EACH( cursor, &apt->stubmgrs )
|
|
||||||
{
|
|
||||||
struct stub_manager *m = LIST_ENTRY( cursor, struct stub_manager, entry );
|
|
||||||
|
|
||||||
if (m->oid == oid)
|
|
||||||
{
|
|
||||||
result = m;
|
|
||||||
stub_manager_int_addref(result);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
LeaveCriticalSection(&apt->cs);
|
|
||||||
|
|
||||||
COM_ApartmentRelease(apt);
|
|
||||||
|
|
||||||
TRACE("found %p from oid %s\n", result, wine_dbgstr_longlong(oid));
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* add some external references (ie from a client that unmarshaled an ifptr) */
|
/* add some external references (ie from a client that unmarshaled an ifptr) */
|
||||||
ULONG stub_manager_ext_addref(struct stub_manager *m, ULONG refs)
|
ULONG stub_manager_ext_addref(struct stub_manager *m, ULONG refs)
|
||||||
{
|
{
|
||||||
|
|
|
@ -317,7 +317,7 @@ static void test_marshal_stub_apartment_shutdown()
|
||||||
|
|
||||||
end_host_object(tid, thread);
|
end_host_object(tid, thread);
|
||||||
|
|
||||||
todo_wine { ok_no_locks(); }
|
ok_no_locks();
|
||||||
|
|
||||||
IUnknown_Release(pProxy);
|
IUnknown_Release(pProxy);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue