- Generate machine-local IPIDs.

- Make pipes be uniquely identified only by their IPID.
This commit is contained in:
Robert Shearman 2005-01-25 10:57:24 +00:00 committed by Alexandre Julliard
parent c1db191d9b
commit ad34f3dc5e
5 changed files with 171 additions and 50 deletions

View File

@ -246,8 +246,10 @@ APARTMENT* COM_CreateApartment(DWORD model)
list_init(&apt->proxies); list_init(&apt->proxies);
list_init(&apt->stubmgrs); list_init(&apt->stubmgrs);
apt->oidc = 1; apt->ipidc = 1;
apt->refs = 1; apt->refs = 1;
apt->remunk_exported = FALSE;
apt->oidc = 1;
InitializeCriticalSection(&apt->cs); InitializeCriticalSection(&apt->cs);
apt->model = model; apt->model = model;
@ -363,6 +365,30 @@ APARTMENT *COM_ApartmentFromOXID(OXID oxid, BOOL ref)
return result; return result;
} }
/* gets the apartment which has a given creator thread ID. The caller must
* release the reference from the apartment as soon as the apartment pointer
* is no longer required. */
APARTMENT *COM_ApartmentFromTID(DWORD tid)
{
APARTMENT *result = NULL;
struct list *cursor;
EnterCriticalSection(&csApartment);
LIST_FOR_EACH( cursor, &apts )
{
struct apartment *apt = LIST_ENTRY( cursor, struct apartment, entry );
if (apt->tid == tid)
{
result = apt;
COM_ApartmentAddRef(result);
break;
}
}
LeaveCriticalSection(&csApartment);
return result;
}
HWND COM_GetApartmentWin(OXID oxid, BOOL ref) HWND COM_GetApartmentWin(OXID oxid, BOOL ref)
{ {
APARTMENT *apt; APARTMENT *apt;

View File

@ -110,6 +110,7 @@ struct proxy_manager
DWORD refs; /* proxy reference count (LOCK) */ DWORD refs; /* proxy reference count (LOCK) */
CRITICAL_SECTION cs; /* thread safety for this object and children */ CRITICAL_SECTION cs; /* thread safety for this object and children */
ULONG sorflags; /* STDOBJREF flags (RO) */ ULONG sorflags; /* STDOBJREF flags (RO) */
IRemUnknown *remunk; /* proxy to IRemUnknown used for lifecycle management (CS cs) */
}; };
/* this needs to become a COM object that implements IRemUnknown */ /* this needs to become a COM object that implements IRemUnknown */
@ -122,13 +123,15 @@ struct apartment
DWORD tid; /* thread id (RO) */ DWORD tid; /* thread id (RO) */
HANDLE thread; /* thread handle (RO) */ HANDLE thread; /* thread handle (RO) */
OXID oxid; /* object exporter ID (RO) */ OXID oxid; /* object exporter ID (RO) */
OID oidc; /* object ID counter, starts at 1, zero is invalid OID (CS cs) */ DWORD ipidc; /* interface pointer ID counter, starts at 1 (CS cs) */
HWND win; /* message window (RO) */ HWND win; /* message window (RO) */
CRITICAL_SECTION cs; /* thread safety */ CRITICAL_SECTION cs; /* thread safety */
LPMESSAGEFILTER filter; /* message filter (CS cs) */ LPMESSAGEFILTER filter; /* message filter (CS cs) */
struct list proxies; /* imported objects (CS cs) */ struct list proxies; /* imported objects (CS cs) */
struct list stubmgrs; /* stub managers for exported objects (CS cs) */ struct list stubmgrs; /* stub managers for exported objects (CS cs) */
BOOL remunk_exported; /* has the IRemUnknown interface for this apartment been created yet? (CS cs) */
OID oidc; /* object ID counter, starts at 1, zero is invalid OID (CS cs). FIXME: remove me */
DWORD listenertid; /* id of apartment_listener_thread. FIXME: remove me */ DWORD listenertid; /* id of apartment_listener_thread. FIXME: remove me */
}; };
@ -177,12 +180,15 @@ ULONG stub_manager_int_release(struct stub_manager *This);
struct stub_manager *new_stub_manager(APARTMENT *apt, IUnknown *object); struct stub_manager *new_stub_manager(APARTMENT *apt, IUnknown *object);
ULONG stub_manager_ext_addref(struct stub_manager *m, ULONG refs); 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 *ipid);
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(APARTMENT *apt, OID oid); struct stub_manager *get_stub_manager(APARTMENT *apt, OID oid);
struct stub_manager *get_stub_manager_from_object(APARTMENT *apt, void *object); struct stub_manager *get_stub_manager_from_object(APARTMENT *apt, void *object);
BOOL stub_manager_notify_unmarshal(struct stub_manager *m, const IPID *ipid); BOOL stub_manager_notify_unmarshal(struct stub_manager *m, const IPID *ipid);
BOOL stub_manager_is_table_marshaled(struct stub_manager *m, const IPID *ipid); BOOL stub_manager_is_table_marshaled(struct stub_manager *m, const IPID *ipid);
HRESULT register_ifstub(APARTMENT *apt, STDOBJREF *stdobjref, REFIID riid, IUnknown *obj, MSHLFLAGS mshlflags);
HRESULT ipid_to_stub_manager(const IPID *ipid, APARTMENT **stub_apt, struct stub_manager **stubmgr_ret);
IRpcStubBuffer *ipid_to_stubbuffer(const IPID *ipid);
HRESULT start_apartment_remote_unknown(void);
IRpcStubBuffer *mid_to_stubbuffer(wine_marshal_id *mid); IRpcStubBuffer *mid_to_stubbuffer(wine_marshal_id *mid);
@ -203,6 +209,7 @@ int WINAPI FileMonikerImpl_DecomposePath(LPCOLESTR str, LPOLESTR** stringTable);
/* compobj.c */ /* compobj.c */
APARTMENT *COM_CreateApartment(DWORD model); APARTMENT *COM_CreateApartment(DWORD model);
APARTMENT *COM_ApartmentFromOXID(OXID oxid, BOOL ref); APARTMENT *COM_ApartmentFromOXID(OXID oxid, BOOL ref);
APARTMENT *COM_ApartmentFromTID(DWORD tid);
DWORD COM_ApartmentAddRef(struct apartment *apt); DWORD COM_ApartmentAddRef(struct apartment *apt);
DWORD COM_ApartmentRelease(struct apartment *apt); DWORD COM_ApartmentRelease(struct apartment *apt);

View File

@ -56,6 +56,8 @@ extern const CLSID CLSID_DfMarshal;
* when the proxy disconnects or is destroyed */ * when the proxy disconnects or is destroyed */
#define SORFP_NOLIFETIMEMGMT SORF_OXRES1 #define SORFP_NOLIFETIMEMGMT SORF_OXRES1
static HRESULT unmarshal_object(const STDOBJREF *stdobjref, APARTMENT *apt, REFIID riid, void **object);
/* Marshalling just passes a unique identifier to the remote client, /* Marshalling just passes a unique identifier to the remote client,
* that makes it possible to find the passed interface again. * that makes it possible to find the passed interface again.
* *
@ -83,35 +85,8 @@ get_facbuf_for_iid(REFIID riid,IPSFactoryBuffer **facbuf) {
return CoGetClassObject(&pxclsid,CLSCTX_INPROC_SERVER,NULL,&IID_IPSFactoryBuffer,(LPVOID*)facbuf); return CoGetClassObject(&pxclsid,CLSCTX_INPROC_SERVER,NULL,&IID_IPSFactoryBuffer,(LPVOID*)facbuf);
} }
IRpcStubBuffer *mid_to_stubbuffer(wine_marshal_id *mid)
{
IRpcStubBuffer *ret;
APARTMENT *apt;
struct stub_manager *m;
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));
return NULL;
}
ret = stub_manager_ipid_to_stubbuffer(m, &mid->ipid);
stub_manager_int_release(m);
COM_ApartmentRelease(apt);
return ret;
}
/* creates a new stub manager and sets stdobjref->oid when stdobjref->oid == 0 */ /* creates a new stub manager and sets stdobjref->oid when stdobjref->oid == 0 */
static HRESULT register_ifstub(APARTMENT *apt, STDOBJREF *stdobjref, REFIID riid, IUnknown *obj, MSHLFLAGS mshlflags) HRESULT register_ifstub(APARTMENT *apt, STDOBJREF *stdobjref, REFIID riid, IUnknown *obj, MSHLFLAGS mshlflags)
{ {
struct stub_manager *manager = NULL; struct stub_manager *manager = NULL;
struct ifstub *ifstub; struct ifstub *ifstub;

View File

@ -59,7 +59,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(ole);
struct request_header struct request_header
{ {
DWORD reqid; DWORD reqid;
wine_marshal_id mid; IPID ipid;
DWORD iMethod; DWORD iMethod;
DWORD cbBuffer; DWORD cbBuffer;
}; };
@ -162,7 +162,6 @@ static DWORD WINAPI stub_dispatch_thread(LPVOID);
static HRESULT static HRESULT
PIPE_RegisterPipe(wine_marshal_id *mid, HANDLE hPipe, BOOL startreader) PIPE_RegisterPipe(wine_marshal_id *mid, HANDLE hPipe, BOOL startreader)
{ {
/* FIXME: this pipe caching code is commented out because it is breaks the /* FIXME: this pipe caching code is commented out because it is breaks the
* tests, causing them hang due to writing to or reading from the wrong pipe. * tests, causing them hang due to writing to or reading from the wrong pipe.
*/ */
@ -205,15 +204,21 @@ PIPE_FindByMID(wine_marshal_id *mid) {
} }
static struct pipe* static struct pipe*
PIPE_GetFromMID(wine_marshal_id *mid) { PIPE_GetFromIPID(const IPID *ipid) {
int i; int i;
for (i=0;i<nrofpipes;i++) { for (i=0; i<nrofpipes; i++)
if ((pipes[i].mid.oxid==mid->oxid) && {
(GetCurrentThreadId()==pipes[i].tid) /* compare TID and PID fields */
) if ((pipes[i].mid.ipid.Data2 == ipid->Data2) &&
return pipes+i; (pipes[i].mid.ipid.Data3 == ipid->Data3) &&
} (GetCurrentThreadId() == pipes[i].tid))
return NULL; return pipes+i;
/* special case for IRemUnknown IPID */
else if ((pipes[i].mid.oxid == *(OXID *)ipid->Data4) &&
(GetCurrentThreadId() == pipes[i].tid))
return pipes+i;
}
return NULL;
} }
static HRESULT static HRESULT
@ -331,7 +336,7 @@ COM_InvokeAndRpcSend(struct rpc *req) {
HRESULT hres; HRESULT hres;
DWORD reqtype; DWORD reqtype;
if (!(stub = mid_to_stubbuffer(&(req->reqh.mid)))) if (!(stub = ipid_to_stubbuffer(&(req->reqh.ipid))))
{ {
ERR("Stub not found?\n"); ERR("Stub not found?\n");
return E_FAIL; return E_FAIL;
@ -366,7 +371,7 @@ RPC_QueueRequestAndWait(struct rpc *req) {
struct rpc *xreq; struct rpc *xreq;
HRESULT hres; HRESULT hres;
DWORD reqtype; DWORD reqtype;
struct pipe *xpipe = PIPE_GetFromMID(&(req->reqh.mid)); struct pipe *xpipe = PIPE_GetFromIPID(&(req->reqh.ipid));
if (!xpipe) { if (!xpipe) {
FIXME("no pipe found.\n"); FIXME("no pipe found.\n");
@ -421,7 +426,7 @@ PipeBuf_SendReceive(LPRPCCHANNELBUFFER iface,RPCOLEMESSAGE* msg,ULONG *status)
if (hres) return hres; if (hres) return hres;
req->reqh.iMethod = msg->iMethod; req->reqh.iMethod = msg->iMethod;
req->reqh.cbBuffer = msg->cbBuffer; req->reqh.cbBuffer = msg->cbBuffer;
memcpy(&(req->reqh.mid),&(This->mid),sizeof(This->mid)); req->reqh.ipid = This->mid.ipid;
req->Buffer = msg->Buffer; req->Buffer = msg->Buffer;
hres = RPC_QueueRequestAndWait(req); hres = RPC_QueueRequestAndWait(req);
if (hres) { if (hres) {

View File

@ -243,11 +243,103 @@ static struct ifstub *stub_manager_ipid_to_ifstub(struct stub_manager *m, const
return result; return result;
} }
IRpcStubBuffer *stub_manager_ipid_to_stubbuffer(struct stub_manager *m, const IPID *ipid) /* gets the stub manager associated with an ipid - 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 */
static struct stub_manager *get_stub_manager_from_ipid(APARTMENT *apt, const IPID *ipid)
{ {
struct ifstub *ifstub = stub_manager_ipid_to_ifstub(m, ipid); struct stub_manager *result = NULL;
struct list *cursor;
return ifstub ? ifstub->stubbuffer : NULL;
EnterCriticalSection(&apt->cs);
LIST_FOR_EACH( cursor, &apt->stubmgrs )
{
struct stub_manager *m = LIST_ENTRY( cursor, struct stub_manager, entry );
if (stub_manager_ipid_to_ifstub(m, ipid))
{
result = m;
stub_manager_int_addref(result);
break;
}
}
LeaveCriticalSection(&apt->cs);
if (result)
TRACE("found %p for ipid %s\n", result, debugstr_guid(ipid));
else
ERR("not found for ipid %s\n", debugstr_guid(ipid));
return result;
}
HRESULT ipid_to_stub_manager(const IPID *ipid, APARTMENT **stub_apt, struct stub_manager **stubmgr_ret)
{
/* FIXME: hack for IRemUnknown */
if (ipid->Data2 == 0xffff)
*stub_apt = COM_ApartmentFromOXID(*(OXID *)ipid->Data4, TRUE);
else
*stub_apt = COM_ApartmentFromTID(ipid->Data2);
if (!*stub_apt)
{
ERR("Couldn't find apartment corresponding to TID 0x%04x\n", ipid->Data2);
return RPC_E_INVALID_OBJECT;
}
*stubmgr_ret = get_stub_manager_from_ipid(*stub_apt, ipid);
if (!*stubmgr_ret)
{
COM_ApartmentRelease(*stub_apt);
*stub_apt = NULL;
return RPC_E_INVALID_OBJECT;
}
return S_OK;
}
IRpcStubBuffer *ipid_to_stubbuffer(const IPID *ipid)
{
IRpcStubBuffer *ret = NULL;
APARTMENT *apt;
struct stub_manager *stubmgr;
struct ifstub *ifstub;
HRESULT hr;
hr = ipid_to_stub_manager(ipid, &apt, &stubmgr);
if (hr != S_OK) return NULL;
ifstub = stub_manager_ipid_to_ifstub(stubmgr, ipid);
if (ifstub)
ret = ifstub->stubbuffer;
stub_manager_int_release(stubmgr);
COM_ApartmentRelease(apt);
return ret;
}
/* generates an ipid in the following format (similar to native version):
* Data1 = apartment-local ipid counter
* Data2 = apartment creator thread ID
* Data3 = process ID
* Data4 = random value
*/
static inline HRESULT generate_ipid(struct stub_manager *m, IPID *ipid)
{
HRESULT hr;
hr = UuidCreate(ipid);
if (FAILED(hr))
{
ERR("couldn't create IPID for stub manager %p\n", m);
UuidCreateNil(ipid);
return hr;
}
EnterCriticalSection(&m->apt->cs);
ipid->Data1 = m->apt->ipidc++;
LeaveCriticalSection(&m->apt->cs);
ipid->Data2 = (USHORT)m->apt->tid;
ipid->Data3 = (USHORT)GetCurrentProcessId();
return S_OK;
} }
/* registers a new interface stub COM object with the stub manager and returns registration record */ /* registers a new interface stub COM object with the stub manager and returns registration record */
@ -273,12 +365,26 @@ struct ifstub *stub_manager_new_ifstub(struct stub_manager *m, IRpcStubBuffer *s
stub->state = IFSTUB_STATE_NORMAL_MARSHALED; stub->state = IFSTUB_STATE_NORMAL_MARSHALED;
stub->iid = *iid; stub->iid = *iid;
stub->ipid = *iid; /* FIXME: should be globally unique */
/* FIXME: hack for IRemUnknown because we don't notify SCM of our IPID
* yet, so we need to use a well-known one */
if (IsEqualIID(iid, &IID_IRemUnknown))
{
stub->ipid.Data1 = 0xffffffff;
stub->ipid.Data2 = 0xffff;
stub->ipid.Data3 = 0xffff;
assert(sizeof(stub->ipid.Data4) == sizeof(m->apt->oxid));
memcpy(&stub->ipid.Data4, &m->apt->oxid, sizeof(OXID));
}
else
generate_ipid(m, &stub->ipid);
EnterCriticalSection(&m->lock); EnterCriticalSection(&m->lock);
list_add_head(&m->ifstubs, &stub->entry); list_add_head(&m->ifstubs, &stub->entry);
LeaveCriticalSection(&m->lock); LeaveCriticalSection(&m->lock);
TRACE("ifstub %p created with ipid %s\n", stub, debugstr_guid(&stub->ipid));
return stub; return stub;
} }
@ -351,3 +457,5 @@ BOOL stub_manager_is_table_marshaled(struct stub_manager *m, const IPID *ipid)
return ret; return ret;
} }
const IID IID_IRemUnknown = { 0x00000131, 0, 0, {0xc0, 0, 0, 0, 0, 0, 0, 0x46} };