ole32: Generate OXID_INFO in the stub manager.

Copy the OXID_INFO from the stub manager, if available, in 
proxy_manager_construct. Otherwise, attempt to resolve it.

Use ipidRemUnknown from OXID_INFO in the proxy manager instead of 
magically generating the IPID for RemUnknown.
This commit is contained in:
Rob Shearman 2007-03-26 18:23:16 +01:00 committed by Alexandre Julliard
parent 1fa24db9fd
commit d1ec56c871
4 changed files with 77 additions and 35 deletions

View File

@ -93,6 +93,7 @@ struct stub_manager
OID oid; /* apartment-scoped unique identifier (RO) */
IUnknown *object; /* the object we are managing the stub for (RO) */
ULONG next_ipid; /* currently unused (LOCK) */
OXID_INFO oxid_info; /* string binding, ipid of rem unknown and other information (RO) */
/* We need to keep a count of the outstanding marshals, so we can enforce the
* marshalling rules (ie, you can only unmarshal normal marshals once). Note
@ -125,6 +126,7 @@ struct proxy_manager
struct apartment *parent; /* owning apartment (RO) */
struct list entry; /* entry in apartment (CS parent->cs) */
OXID oxid; /* object exported ID (RO) */
OXID_INFO oxid_info; /* string binding, ipid of rem unknown and other information (RO) */
OID oid; /* object ID (RO) */
struct list interfaces; /* imported interfaces (CS cs) */
LONG refs; /* proxy reference count (LOCK) */
@ -227,6 +229,7 @@ void RPC_StopLocalServer(void *registration);
HRESULT RPC_GetLocalClassObject(REFCLSID rclsid, REFIID iid, LPVOID *ppv);
HRESULT RPC_RegisterChannelHook(REFGUID rguid, IChannelHook *hook);
void RPC_UnregisterAllChannelHooks(void);
HRESULT RPC_ResolveOxid(OXID oxid, OXID_INFO *oxid_info);
/* This function initialize the Running Object Table */
HRESULT WINAPI RunningObjectTableImpl_Initialize(void);

View File

@ -51,7 +51,8 @@ extern const CLSID CLSID_DfMarshal;
static HRESULT unmarshal_object(const STDOBJREF *stdobjref, APARTMENT *apt,
MSHCTX dest_context, void *dest_context_data,
REFIID riid, void **object);
REFIID riid, const OXID_INFO *oxid_info,
void **object);
/* Marshalling just passes a unique identifier to the remote client,
* that makes it possible to find the passed interface again.
@ -299,7 +300,7 @@ static HRESULT WINAPI ClientIdentity_QueryMultipleInterfaces(IMultiQI *iface, UL
hrobj = unmarshal_object(&qiresults[i].std, This->parent,
This->dest_context,
This->dest_context_data,
pMQIs[index].pIID,
pMQIs[index].pIID, &This->oxid_info,
(void **)&pMQIs[index].pItf);
if (hrobj == S_OK)
@ -651,7 +652,7 @@ static void ifproxy_destroy(struct ifproxy * This)
static HRESULT proxy_manager_construct(
APARTMENT * apt, ULONG sorflags, OXID oxid, OID oid,
struct proxy_manager ** proxy_manager)
const OXID_INFO *oxid_info, struct proxy_manager ** proxy_manager)
{
struct proxy_manager * This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
if (!This) return E_OUTOFMEMORY;
@ -663,6 +664,25 @@ static HRESULT proxy_manager_construct(
return HRESULT_FROM_WIN32(GetLastError());
}
if (oxid_info)
{
This->oxid_info.dwPid = oxid_info->dwPid;
This->oxid_info.dwTid = oxid_info->dwTid;
This->oxid_info.ipidRemUnknown = oxid_info->ipidRemUnknown;
This->oxid_info.dwAuthnHint = oxid_info->dwAuthnHint;
This->oxid_info.psa = NULL /* FIXME: copy from oxid_info */;
}
else
{
HRESULT hr = RPC_ResolveOxid(oxid, &This->oxid_info);
if (FAILED(hr))
{
CloseHandle(This->remoting_mutex);
HeapFree(GetProcessHeap(), 0, This);
return hr;
}
}
This->lpVtbl = &ClientIdentity_Vtbl;
This->lpVtblMarshal = &ProxyMarshal_Vtbl;
This->lpVtblCliSec = &ProxyCliSec_Vtbl;
@ -951,19 +971,12 @@ static HRESULT proxy_manager_get_remunknown(struct proxy_manager * This, IRemUnk
stdobjref.oxid = This->oxid;
/* FIXME: what should be used for the oid? The DCOM draft doesn't say */
stdobjref.oid = (OID)-1;
/* FIXME: this is a hack around not having an OXID resolver yet -
* the OXID resolver should give us the IPID of the IRemUnknown
* interface */
stdobjref.ipid.Data1 = 0xffffffff;
stdobjref.ipid.Data2 = 0xffff;
stdobjref.ipid.Data3 = 0xffff;
assert(sizeof(stdobjref.ipid.Data4) == sizeof(stdobjref.oxid));
memcpy(&stdobjref.ipid.Data4, &stdobjref.oxid, sizeof(OXID));
stdobjref.ipid = This->oxid_info.ipidRemUnknown;
/* do the unmarshal */
hr = unmarshal_object(&stdobjref, This->parent, This->dest_context,
This->dest_context_data, &IID_IRemUnknown,
(void**)&This->remunk);
&This->oxid_info, (void**)&This->remunk);
if (hr == S_OK)
*remunk = This->remunk;
}
@ -1010,6 +1023,7 @@ static void proxy_manager_destroy(struct proxy_manager * This)
}
if (This->remunk) IRemUnknown_Release(This->remunk);
CoTaskMemFree(This->oxid_info.psa);
DEBUG_CLEAR_CRITSEC_NAME(&This->cs);
DeleteCriticalSection(&This->cs);
@ -1156,7 +1170,8 @@ StdMarshalImpl_MarshalInterface(
* and table marshaling */
static HRESULT unmarshal_object(const STDOBJREF *stdobjref, APARTMENT *apt,
MSHCTX dest_context, void *dest_context_data,
REFIID riid, void **object)
REFIID riid, const OXID_INFO *oxid_info,
void **object)
{
struct proxy_manager *proxy_manager = NULL;
HRESULT hr = S_OK;
@ -1174,7 +1189,7 @@ static HRESULT unmarshal_object(const STDOBJREF *stdobjref, APARTMENT *apt,
if (!find_proxy_manager(apt, stdobjref->oxid, stdobjref->oid, &proxy_manager))
{
hr = proxy_manager_construct(apt, stdobjref->flags,
stdobjref->oxid, stdobjref->oid,
stdobjref->oxid, stdobjref->oid, oxid_info,
&proxy_manager);
}
else
@ -1225,7 +1240,7 @@ static HRESULT WINAPI
StdMarshalImpl_UnmarshalInterface(LPMARSHAL iface, IStream *pStm, REFIID riid, void **ppv)
{
StdMarshalImpl *This = (StdMarshalImpl *)iface;
struct stub_manager *stubmgr;
struct stub_manager *stubmgr = NULL;
STDOBJREF stdobjref;
ULONG res;
HRESULT hres;
@ -1276,8 +1291,6 @@ StdMarshalImpl_UnmarshalInterface(LPMARSHAL iface, IStream *pStm, REFIID riid, v
{
if (!stub_manager_notify_unmarshal(stubmgr, &stdobjref.ipid))
hres = CO_E_OBJNOTCONNECTED;
stub_manager_int_release(stubmgr);
}
else
{
@ -1286,8 +1299,6 @@ StdMarshalImpl_UnmarshalInterface(LPMARSHAL iface, IStream *pStm, REFIID riid, v
wine_dbgstr_longlong(stdobjref.oid));
hres = CO_E_OBJNOTCONNECTED;
}
apartment_release(stub_apt);
}
else
TRACE("Treating unmarshal from OXID %s as inter-process\n",
@ -1295,7 +1306,11 @@ StdMarshalImpl_UnmarshalInterface(LPMARSHAL iface, IStream *pStm, REFIID riid, v
if (hres == S_OK)
hres = unmarshal_object(&stdobjref, apt, This->dwDestContext,
This->pvDestContext, riid, ppv);
This->pvDestContext, riid,
stubmgr ? &stubmgr->oxid_info : NULL, ppv);
if (stubmgr) stub_manager_int_release(stubmgr);
if (stub_apt) apartment_release(stub_apt);
if (hres) WARN("Failed with error 0x%08x\n", hres);
else TRACE("Successfully created proxy %p\n", *ppv);

View File

@ -1488,6 +1488,23 @@ void RPC_UnregisterInterface(REFIID riid)
LeaveCriticalSection(&csRegIf);
}
HRESULT RPC_ResolveOxid(OXID oxid, OXID_INFO *oxid_info)
{
oxid_info->dwTid = 0;
oxid_info->dwPid = 0;
oxid_info->dwAuthnHint = RPC_C_AUTHN_LEVEL_NONE;
/* FIXME: this is a hack around not having an OXID resolver yet -
* this function should contact the machine's OXID resolver and then it
* should give us the IPID of the IRemUnknown interface */
oxid_info->ipidRemUnknown.Data1 = 0xffffffff;
oxid_info->ipidRemUnknown.Data2 = 0xffff;
oxid_info->ipidRemUnknown.Data3 = 0xffff;
memcpy(&oxid_info->ipidRemUnknown.Data4, &oxid, sizeof(OXID));
oxid_info->psa = NULL /* FIXME */;
return S_OK;
}
/* make the apartment reachable by other threads and processes and create the
* IRemUnknown object */
void RPC_StartRemoting(struct apartment *apt)

View File

@ -70,6 +70,23 @@ struct stub_manager *new_stub_manager(APARTMENT *apt, IUnknown *object)
* and the caller will also hold a reference */
sm->refs = 2;
sm->oxid_info.dwPid = GetCurrentProcessId();
sm->oxid_info.dwTid = GetCurrentThreadId();
/*
* FIXME: this is a hack for marshalling IRemUnknown. In real
* DCOM, the IPID of the IRemUnknown interface is generated like
* any other and passed to the OXID resolver which then returns it
* when queried. We don't have an OXID resolver yet so instead we
* use a magic IPID reserved for IRemUnknown.
*/
sm->oxid_info.ipidRemUnknown.Data1 = 0xffffffff;
sm->oxid_info.ipidRemUnknown.Data2 = 0xffff;
sm->oxid_info.ipidRemUnknown.Data3 = 0xffff;
assert(sizeof(sm->oxid_info.ipidRemUnknown.Data4) == sizeof(apt->oxid));
memcpy(&sm->oxid_info.ipidRemUnknown.Data4, &apt->oxid, sizeof(OXID));
sm->oxid_info.dwAuthnHint = RPC_C_AUTHN_LEVEL_NONE;
sm->oxid_info.psa = NULL /* FIXME */;
/* yes, that's right, this starts at zero. that's zero EXTERNAL
* refs, ie nobody has unmarshalled anything yet. we can't have
* negative refs because the stub manager cannot be explicitly
@ -102,6 +119,7 @@ static void stub_manager_delete(struct stub_manager *m)
stub_manager_delete_ifstub(m, ifstub);
}
CoTaskMemFree(m->oxid_info.psa);
IUnknown_Release(m->object);
DEBUG_CLEAR_CRITSEC_NAME(&m->lock);
@ -451,21 +469,10 @@ struct ifstub *stub_manager_new_ifstub(struct stub_manager *m, IRpcStubBuffer *s
stub->flags = flags;
stub->iid = *iid;
/*
* FIXME: this is a hack for marshalling IRemUnknown. In real
* DCOM, the IPID of the IRemUnknown interface is generated like
* any other and passed to the OXID resolver which then returns it
* when queried. We don't have an OXID resolver yet so instead we
* use a magic IPID reserved for IRemUnknown.
*/
/* FIXME: find a cleaner way of identifying that we are creating an ifstub
* for the remunknown interface */
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));
}
stub->ipid = m->oxid_info.ipidRemUnknown;
else
generate_ipid(m, &stub->ipid);