- Generate machine-local IPIDs.
- Make pipes be uniquely identified only by their IPID.
This commit is contained in:
parent
c1db191d9b
commit
ad34f3dc5e
|
@ -246,8 +246,10 @@ APARTMENT* COM_CreateApartment(DWORD model)
|
|||
|
||||
list_init(&apt->proxies);
|
||||
list_init(&apt->stubmgrs);
|
||||
apt->oidc = 1;
|
||||
apt->ipidc = 1;
|
||||
apt->refs = 1;
|
||||
apt->remunk_exported = FALSE;
|
||||
apt->oidc = 1;
|
||||
InitializeCriticalSection(&apt->cs);
|
||||
|
||||
apt->model = model;
|
||||
|
@ -363,6 +365,30 @@ APARTMENT *COM_ApartmentFromOXID(OXID oxid, BOOL ref)
|
|||
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)
|
||||
{
|
||||
APARTMENT *apt;
|
||||
|
|
|
@ -110,6 +110,7 @@ struct proxy_manager
|
|||
DWORD refs; /* proxy reference count (LOCK) */
|
||||
CRITICAL_SECTION cs; /* thread safety for this object and children */
|
||||
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 */
|
||||
|
@ -122,13 +123,15 @@ struct apartment
|
|||
DWORD tid; /* thread id (RO) */
|
||||
HANDLE thread; /* thread handle (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) */
|
||||
CRITICAL_SECTION cs; /* thread safety */
|
||||
LPMESSAGEFILTER filter; /* message filter (CS cs) */
|
||||
struct list proxies; /* imported 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 */
|
||||
};
|
||||
|
||||
|
@ -177,12 +180,15 @@ ULONG stub_manager_int_release(struct stub_manager *This);
|
|||
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_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 stub_manager *get_stub_manager(APARTMENT *apt, OID oid);
|
||||
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_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);
|
||||
|
||||
|
@ -203,6 +209,7 @@ int WINAPI FileMonikerImpl_DecomposePath(LPCOLESTR str, LPOLESTR** stringTable);
|
|||
/* compobj.c */
|
||||
APARTMENT *COM_CreateApartment(DWORD model);
|
||||
APARTMENT *COM_ApartmentFromOXID(OXID oxid, BOOL ref);
|
||||
APARTMENT *COM_ApartmentFromTID(DWORD tid);
|
||||
DWORD COM_ApartmentAddRef(struct apartment *apt);
|
||||
DWORD COM_ApartmentRelease(struct apartment *apt);
|
||||
|
||||
|
|
|
@ -56,6 +56,8 @@ extern const CLSID CLSID_DfMarshal;
|
|||
* when the proxy disconnects or is destroyed */
|
||||
#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,
|
||||
* 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);
|
||||
}
|
||||
|
||||
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 */
|
||||
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 ifstub *ifstub;
|
||||
|
|
|
@ -59,7 +59,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(ole);
|
|||
struct request_header
|
||||
{
|
||||
DWORD reqid;
|
||||
wine_marshal_id mid;
|
||||
IPID ipid;
|
||||
DWORD iMethod;
|
||||
DWORD cbBuffer;
|
||||
};
|
||||
|
@ -162,7 +162,6 @@ static DWORD WINAPI stub_dispatch_thread(LPVOID);
|
|||
static HRESULT
|
||||
PIPE_RegisterPipe(wine_marshal_id *mid, HANDLE hPipe, BOOL startreader)
|
||||
{
|
||||
|
||||
/* 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.
|
||||
*/
|
||||
|
@ -205,15 +204,21 @@ PIPE_FindByMID(wine_marshal_id *mid) {
|
|||
}
|
||||
|
||||
static struct pipe*
|
||||
PIPE_GetFromMID(wine_marshal_id *mid) {
|
||||
int i;
|
||||
for (i=0;i<nrofpipes;i++) {
|
||||
if ((pipes[i].mid.oxid==mid->oxid) &&
|
||||
(GetCurrentThreadId()==pipes[i].tid)
|
||||
)
|
||||
return pipes+i;
|
||||
}
|
||||
return NULL;
|
||||
PIPE_GetFromIPID(const IPID *ipid) {
|
||||
int i;
|
||||
for (i=0; i<nrofpipes; i++)
|
||||
{
|
||||
/* compare TID and PID fields */
|
||||
if ((pipes[i].mid.ipid.Data2 == ipid->Data2) &&
|
||||
(pipes[i].mid.ipid.Data3 == ipid->Data3) &&
|
||||
(GetCurrentThreadId() == pipes[i].tid))
|
||||
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
|
||||
|
@ -331,7 +336,7 @@ COM_InvokeAndRpcSend(struct rpc *req) {
|
|||
HRESULT hres;
|
||||
DWORD reqtype;
|
||||
|
||||
if (!(stub = mid_to_stubbuffer(&(req->reqh.mid))))
|
||||
if (!(stub = ipid_to_stubbuffer(&(req->reqh.ipid))))
|
||||
{
|
||||
ERR("Stub not found?\n");
|
||||
return E_FAIL;
|
||||
|
@ -366,7 +371,7 @@ RPC_QueueRequestAndWait(struct rpc *req) {
|
|||
struct rpc *xreq;
|
||||
HRESULT hres;
|
||||
DWORD reqtype;
|
||||
struct pipe *xpipe = PIPE_GetFromMID(&(req->reqh.mid));
|
||||
struct pipe *xpipe = PIPE_GetFromIPID(&(req->reqh.ipid));
|
||||
|
||||
if (!xpipe) {
|
||||
FIXME("no pipe found.\n");
|
||||
|
@ -421,7 +426,7 @@ PipeBuf_SendReceive(LPRPCCHANNELBUFFER iface,RPCOLEMESSAGE* msg,ULONG *status)
|
|||
if (hres) return hres;
|
||||
req->reqh.iMethod = msg->iMethod;
|
||||
req->reqh.cbBuffer = msg->cbBuffer;
|
||||
memcpy(&(req->reqh.mid),&(This->mid),sizeof(This->mid));
|
||||
req->reqh.ipid = This->mid.ipid;
|
||||
req->Buffer = msg->Buffer;
|
||||
hres = RPC_QueueRequestAndWait(req);
|
||||
if (hres) {
|
||||
|
|
|
@ -243,11 +243,103 @@ static struct ifstub *stub_manager_ipid_to_ifstub(struct stub_manager *m, const
|
|||
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);
|
||||
|
||||
return ifstub ? ifstub->stubbuffer : NULL;
|
||||
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 (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 */
|
||||
|
@ -273,12 +365,26 @@ struct ifstub *stub_manager_new_ifstub(struct stub_manager *m, IRpcStubBuffer *s
|
|||
stub->state = IFSTUB_STATE_NORMAL_MARSHALED;
|
||||
|
||||
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);
|
||||
list_add_head(&m->ifstubs, &stub->entry);
|
||||
LeaveCriticalSection(&m->lock);
|
||||
|
||||
TRACE("ifstub %p created with ipid %s\n", stub, debugstr_guid(&stub->ipid));
|
||||
|
||||
return stub;
|
||||
}
|
||||
|
||||
|
@ -351,3 +457,5 @@ BOOL stub_manager_is_table_marshaled(struct stub_manager *m, const IPID *ipid)
|
|||
|
||||
return ret;
|
||||
}
|
||||
|
||||
const IID IID_IRemUnknown = { 0x00000131, 0, 0, {0xc0, 0, 0, 0, 0, 0, 0, 0x46} };
|
||||
|
|
Loading…
Reference in New Issue