mirror of
https://github.com/reactos/wine.git
synced 2025-02-17 19:39:00 +00:00
- Make proxy manager use IMultiQI instead of IInternalUnknown as tests
show that IInternalUnknown isn't exposed. - Implement IMultiQI on top of IRemUnknown calls. - Silence some fixmes that occur during tests and don't give us any useful information. - Fix typo in class factory proxy that caused us to use the wrong offset into the CFProxy structure, causing us to not call the outer_unknown properly.
This commit is contained in:
parent
b6317bd537
commit
3018974ce3
@ -100,7 +100,7 @@ struct ifproxy
|
||||
/* imported object / proxy manager */
|
||||
struct proxy_manager
|
||||
{
|
||||
const IInternalUnknownVtbl *lpVtbl;
|
||||
const IMultiQIVtbl *lpVtbl;
|
||||
struct apartment *parent; /* owning apartment (RO) */
|
||||
struct list entry; /* entry in apartment (CS parent->cs) */
|
||||
LPRPCCHANNELBUFFER chan; /* channel to object (CS cs) */
|
||||
|
@ -171,47 +171,30 @@ HRESULT register_ifstub(APARTMENT *apt, STDOBJREF *stdobjref, REFIID riid, IUnkn
|
||||
static HRESULT proxy_manager_get_remunknown(struct proxy_manager * This, IRemUnknown **remunk);
|
||||
static void proxy_manager_destroy(struct proxy_manager * This);
|
||||
static HRESULT proxy_manager_find_ifproxy(struct proxy_manager * This, REFIID riid, struct ifproxy ** ifproxy_found);
|
||||
static HRESULT proxy_manager_query_local_interface(struct proxy_manager * This, REFIID riid, void ** ppv);
|
||||
|
||||
static HRESULT WINAPI ClientIdentity_QueryInterface(IInternalUnknown * iface, REFIID riid, void ** ppv)
|
||||
static HRESULT WINAPI ClientIdentity_QueryInterface(IMultiQI * iface, REFIID riid, void ** ppv)
|
||||
{
|
||||
struct proxy_manager * This = (struct proxy_manager *)iface;
|
||||
HRESULT hr;
|
||||
struct ifproxy * ifproxy;
|
||||
MULTI_QI mqi;
|
||||
|
||||
TRACE("%s\n", debugstr_guid(riid));
|
||||
|
||||
if (IsEqualIID(riid, &IID_IUnknown) ||
|
||||
IsEqualIID(riid, &IID_IInternalUnknown))
|
||||
{
|
||||
*ppv = (void *)iface;
|
||||
IInternalUnknown_AddRef(iface);
|
||||
return S_OK;
|
||||
}
|
||||
mqi.pIID = riid;
|
||||
hr = IMultiQI_QueryMultipleInterfaces(iface, 1, &mqi);
|
||||
*ppv = (void *)mqi.pItf;
|
||||
|
||||
hr = proxy_manager_find_ifproxy(This, riid, &ifproxy);
|
||||
if (hr == S_OK)
|
||||
{
|
||||
*ppv = ifproxy->iface;
|
||||
IUnknown_AddRef((IUnknown *)*ppv);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
FIXME("interface not found %s\n", debugstr_guid(riid));
|
||||
|
||||
/* FIXME: call IRemUnknown::RemQueryInterface */
|
||||
|
||||
*ppv = NULL;
|
||||
return E_NOINTERFACE;
|
||||
return hr;
|
||||
}
|
||||
|
||||
static ULONG WINAPI ClientIdentity_AddRef(IInternalUnknown * iface)
|
||||
static ULONG WINAPI ClientIdentity_AddRef(IMultiQI * iface)
|
||||
{
|
||||
struct proxy_manager * This = (struct proxy_manager *)iface;
|
||||
TRACE("%p - before %ld\n", iface, This->refs);
|
||||
return InterlockedIncrement(&This->refs);
|
||||
}
|
||||
|
||||
static ULONG WINAPI ClientIdentity_Release(IInternalUnknown * iface)
|
||||
static ULONG WINAPI ClientIdentity_Release(IMultiQI * iface)
|
||||
{
|
||||
struct proxy_manager * This = (struct proxy_manager *)iface;
|
||||
ULONG refs = InterlockedDecrement(&This->refs);
|
||||
@ -221,54 +204,139 @@ static ULONG WINAPI ClientIdentity_Release(IInternalUnknown * iface)
|
||||
return refs;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI ClientIdentity_QueryInternalInterface(IInternalUnknown * iface, REFIID riid, void ** ppv)
|
||||
static HRESULT WINAPI ClientIdentity_QueryMultipleInterfaces(IMultiQI *iface, ULONG cMQIs, MULTI_QI *pMQIs)
|
||||
{
|
||||
FIXME("(%s, %p): stub!\n", debugstr_guid(riid), ppv);
|
||||
return E_NOINTERFACE;
|
||||
struct proxy_manager * This = (struct proxy_manager *)iface;
|
||||
REMQIRESULT *qiresults = NULL;
|
||||
ULONG nonlocal_mqis = 0;
|
||||
ULONG i;
|
||||
ULONG successful_mqis = 0;
|
||||
IID *iids = HeapAlloc(GetProcessHeap(), 0, cMQIs * sizeof(*iids));
|
||||
/* mapping of RemQueryInterface index to QueryMultipleInterfaces index */
|
||||
ULONG *mapping = HeapAlloc(GetProcessHeap(), 0, cMQIs * sizeof(*mapping));
|
||||
|
||||
TRACE("cMQIs: %ld\n", cMQIs);
|
||||
|
||||
/* try to get a local interface - this includes already active proxy
|
||||
* interfaces and also interfaces exposed by the proxy manager */
|
||||
for (i = 0; i < cMQIs; i++)
|
||||
{
|
||||
TRACE("iid[%ld] = %s\n", i, debugstr_guid(pMQIs[i].pIID));
|
||||
pMQIs[i].hr = proxy_manager_query_local_interface(This, pMQIs[i].pIID, (void **)&pMQIs[i].pItf);
|
||||
if (pMQIs[i].hr == S_OK)
|
||||
successful_mqis++;
|
||||
else
|
||||
{
|
||||
iids[nonlocal_mqis] = *pMQIs[i].pIID;
|
||||
mapping[nonlocal_mqis] = i;
|
||||
nonlocal_mqis++;
|
||||
}
|
||||
}
|
||||
|
||||
TRACE("%ld interfaces not found locally\n", nonlocal_mqis);
|
||||
|
||||
/* if we have more than one interface not found locally then we must try
|
||||
* to query the remote object for it */
|
||||
if (nonlocal_mqis != 0)
|
||||
{
|
||||
IRemUnknown *remunk;
|
||||
HRESULT hr;
|
||||
IPID *ipid;
|
||||
|
||||
/* get the ipid of the first entry */
|
||||
/* FIXME: should we implement ClientIdentity on the ifproxies instead
|
||||
* of the proxy_manager so we use the correct ipid here? */
|
||||
ipid = &LIST_ENTRY(list_head(&This->interfaces), struct ifproxy, entry)->ipid;
|
||||
|
||||
/* get IRemUnknown proxy so we can communicate with the remote object */
|
||||
hr = proxy_manager_get_remunknown(This, &remunk);
|
||||
|
||||
if (hr == S_OK)
|
||||
{
|
||||
hr = IRemUnknown_RemQueryInterface(remunk, ipid, NORMALEXTREFS,
|
||||
nonlocal_mqis, iids, &qiresults);
|
||||
if (FAILED(hr))
|
||||
ERR("IRemUnknown_RemQueryInterface failed with error 0x%08lx\n", hr);
|
||||
}
|
||||
|
||||
/* IRemUnknown_RemQueryInterface can return S_FALSE if only some of
|
||||
* the interfaces were returned */
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
/* try to unmarshal each object returned to us */
|
||||
for (i = 0; i < nonlocal_mqis; i++)
|
||||
{
|
||||
ULONG index = mapping[i];
|
||||
HRESULT hrobj = qiresults[i].hResult;
|
||||
if (hrobj == S_OK)
|
||||
hrobj = unmarshal_object(&qiresults[i].std, This->parent,
|
||||
pMQIs[index].pIID,
|
||||
(void **)&pMQIs[index].pItf);
|
||||
|
||||
if (hrobj == S_OK)
|
||||
successful_mqis++;
|
||||
else
|
||||
ERR("Failed to get pointer to interface %s\n", debugstr_guid(pMQIs[index].pIID));
|
||||
pMQIs[index].hr = hrobj;
|
||||
}
|
||||
}
|
||||
|
||||
/* free the memory allocated by the proxy */
|
||||
CoTaskMemFree(qiresults);
|
||||
}
|
||||
|
||||
TRACE("%ld/%ld successfully queried\n", successful_mqis, cMQIs);
|
||||
|
||||
HeapFree(GetProcessHeap(), 0, iids);
|
||||
HeapFree(GetProcessHeap(), 0, mapping);
|
||||
|
||||
if (successful_mqis == cMQIs)
|
||||
return S_OK; /* we got all requested interfaces */
|
||||
else if (successful_mqis == 0)
|
||||
return E_NOINTERFACE; /* we didn't get any interfaces */
|
||||
else
|
||||
return S_FALSE; /* we got some interfaces */
|
||||
}
|
||||
|
||||
static const IInternalUnknownVtbl ClientIdentity_Vtbl =
|
||||
static const IMultiQIVtbl ClientIdentity_Vtbl =
|
||||
{
|
||||
ClientIdentity_QueryInterface,
|
||||
ClientIdentity_AddRef,
|
||||
ClientIdentity_Release,
|
||||
ClientIdentity_QueryInternalInterface
|
||||
ClientIdentity_QueryMultipleInterfaces
|
||||
};
|
||||
|
||||
static HRESULT ifproxy_get_public_ref(struct ifproxy * This)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
/* FIXME: as this call could possibly be going over the network, we
|
||||
* are going to spend a long time in this CS. We might want to replace
|
||||
* this with a mutex */
|
||||
EnterCriticalSection(&This->parent->cs);
|
||||
if (This->refs == 0)
|
||||
{
|
||||
APARTMENT * apt;
|
||||
IRemUnknown *remunk = NULL;
|
||||
|
||||
TRACE("getting public ref for ifproxy %p\n", This);
|
||||
|
||||
/* FIXME: call IRemUnknown::RemAddRef if necessary */
|
||||
|
||||
/* FIXME: this is a hack around not yet implemented IRemUnknown */
|
||||
if ((apt = COM_ApartmentFromOXID(This->parent->oxid, TRUE)))
|
||||
hr = proxy_manager_get_remunknown(This->parent, &remunk);
|
||||
if (hr == S_OK)
|
||||
{
|
||||
struct stub_manager * stubmgr;
|
||||
if ((stubmgr = get_stub_manager(apt, This->parent->oid)))
|
||||
{
|
||||
stub_manager_ext_addref(stubmgr, 1);
|
||||
This->refs += 1;
|
||||
|
||||
stub_manager_int_release(stubmgr);
|
||||
}
|
||||
|
||||
COM_ApartmentRelease(apt);
|
||||
HRESULT hrref;
|
||||
REMINTERFACEREF rif;
|
||||
rif.ipid = This->ipid;
|
||||
rif.cPublicRefs = NORMALEXTREFS;
|
||||
rif.cPrivateRefs = 0;
|
||||
hr = IRemUnknown_RemAddRef(remunk, 1, &rif, &hrref);
|
||||
if (hr == S_OK && hrref == S_OK)
|
||||
This->refs += NORMALEXTREFS;
|
||||
else
|
||||
ERR("IRemUnknown_RemAddRef returned with 0x%08lx, hrref = 0x%08lx\n", hr, hrref);
|
||||
}
|
||||
else
|
||||
FIXME("Need to implement IRemUnknown for inter-process table marshaling\n");
|
||||
}
|
||||
LeaveCriticalSection(&This->parent->cs);
|
||||
|
||||
return S_OK;
|
||||
return hr;
|
||||
}
|
||||
|
||||
static HRESULT ifproxy_release_public_refs(struct ifproxy * This)
|
||||
@ -371,6 +439,33 @@ static HRESULT proxy_manager_construct(
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT proxy_manager_query_local_interface(struct proxy_manager * This, REFIID riid, void ** ppv)
|
||||
{
|
||||
HRESULT hr;
|
||||
struct ifproxy * ifproxy;
|
||||
|
||||
TRACE("%s\n", debugstr_guid(riid));
|
||||
|
||||
if (IsEqualIID(riid, &IID_IUnknown) ||
|
||||
IsEqualIID(riid, &IID_IMultiQI))
|
||||
{
|
||||
*ppv = (void *)&This->lpVtbl;
|
||||
IMultiQI_AddRef((IMultiQI *)&This->lpVtbl);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
hr = proxy_manager_find_ifproxy(This, riid, &ifproxy);
|
||||
if (hr == S_OK)
|
||||
{
|
||||
*ppv = ifproxy->iface;
|
||||
IUnknown_AddRef((IUnknown *)*ppv);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
*ppv = NULL;
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
static HRESULT proxy_manager_create_ifproxy(
|
||||
struct proxy_manager * This, IPID ipid, REFIID riid, ULONG cPublicRefs,
|
||||
struct ifproxy ** iif_out)
|
||||
@ -582,7 +677,7 @@ static BOOL find_proxy_manager(APARTMENT * apt, OXID oxid, OID oid, struct proxy
|
||||
if ((oxid == proxy->oxid) && (oid == proxy->oid))
|
||||
{
|
||||
*proxy_found = proxy;
|
||||
ClientIdentity_AddRef((IInternalUnknown *)&proxy->lpVtbl);
|
||||
ClientIdentity_AddRef((IMultiQI *)&proxy->lpVtbl);
|
||||
found = TRUE;
|
||||
break;
|
||||
}
|
||||
@ -754,7 +849,7 @@ static HRESULT unmarshal_object(const STDOBJREF *stdobjref, APARTMENT *apt, REFI
|
||||
* IUnknown of the proxy manager. */
|
||||
if (IsEqualIID(riid, &IID_IUnknown))
|
||||
{
|
||||
ClientIdentity_AddRef((IInternalUnknown*)&proxy_manager->lpVtbl);
|
||||
ClientIdentity_AddRef((IMultiQI*)&proxy_manager->lpVtbl);
|
||||
*object = (LPVOID)(&proxy_manager->lpVtbl);
|
||||
}
|
||||
else
|
||||
@ -769,7 +864,7 @@ static HRESULT unmarshal_object(const STDOBJREF *stdobjref, APARTMENT *apt, REFI
|
||||
if (hr == S_OK)
|
||||
{
|
||||
/* FIXME: push this AddRef inside proxy_manager_find_ifproxy/create_ifproxy? */
|
||||
ClientIdentity_AddRef((IInternalUnknown*)&proxy_manager->lpVtbl);
|
||||
ClientIdentity_AddRef((IMultiQI*)&proxy_manager->lpVtbl);
|
||||
*object = ifproxy->iface;
|
||||
}
|
||||
}
|
||||
@ -777,7 +872,7 @@ static HRESULT unmarshal_object(const STDOBJREF *stdobjref, APARTMENT *apt, REFI
|
||||
|
||||
/* release our reference to the proxy manager - the client/apartment
|
||||
* will hold on to the remaining reference for us */
|
||||
if (proxy_manager) ClientIdentity_Release((IInternalUnknown*)&proxy_manager->lpVtbl);
|
||||
if (proxy_manager) ClientIdentity_Release((IMultiQI*)&proxy_manager->lpVtbl);
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
@ -319,7 +319,7 @@ static void WINAPI IRpcProxyBufferImpl_Disconnect(LPRPCPROXYBUFFER iface) {
|
||||
|
||||
static HRESULT WINAPI
|
||||
CFProxy_QueryInterface(LPCLASSFACTORY iface,REFIID riid, LPVOID *ppv) {
|
||||
ICOM_THIS_MULTI(CFProxy,lpvtbl_proxy,iface);
|
||||
ICOM_THIS_MULTI(CFProxy,lpvtbl_cf,iface);
|
||||
if (This->outer_unknown) return IUnknown_QueryInterface(This->outer_unknown, riid, ppv);
|
||||
*ppv = NULL;
|
||||
if (IsEqualIID(&IID_IClassFactory,riid) || IsEqualIID(&IID_IUnknown,riid)) {
|
||||
|
@ -129,6 +129,11 @@ read_pipe(HANDLE hf, LPVOID ptr, DWORD size) {
|
||||
return E_FAIL;
|
||||
}
|
||||
if (res!=size) {
|
||||
if (!res)
|
||||
{
|
||||
WARN("%p disconnected\n", hf);
|
||||
return RPC_E_DISCONNECTED;
|
||||
}
|
||||
FIXME("Read only %ld of %ld bytes from %p.\n",res,size,hf);
|
||||
return E_FAIL;
|
||||
}
|
||||
@ -310,10 +315,8 @@ COM_InvokeAndRpcSend(struct rpc *req) {
|
||||
DWORD reqtype;
|
||||
|
||||
if (!(stub = ipid_to_stubbuffer(&(req->reqh.ipid))))
|
||||
{
|
||||
ERR("Stub not found?\n");
|
||||
return E_FAIL;
|
||||
}
|
||||
/* ipid_to_stubbuffer will already have logged the error */
|
||||
return RPC_E_DISCONNECTED;
|
||||
|
||||
IUnknown_AddRef(stub);
|
||||
msg.Buffer = req->Buffer;
|
||||
@ -417,8 +420,9 @@ PipeBuf_SendReceive(LPRPCCHANNELBUFFER iface,RPCOLEMESSAGE* msg,ULONG *status)
|
||||
static HRESULT WINAPI
|
||||
PipeBuf_FreeBuffer(LPRPCCHANNELBUFFER iface,RPCOLEMESSAGE* msg)
|
||||
{
|
||||
FIXME("(%p), stub!\n",msg);
|
||||
return E_FAIL;
|
||||
TRACE("(%p)\n",msg);
|
||||
HeapFree(GetProcessHeap(), 0, msg->Buffer);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI
|
||||
|
@ -539,6 +539,7 @@ static HRESULT WINAPI RemUnknown_RemQueryInterface(IRemUnknown *iface,
|
||||
{
|
||||
HRESULT hr;
|
||||
USHORT i;
|
||||
USHORT successful_qis = 0;
|
||||
APARTMENT *apt;
|
||||
struct stub_manager *stubmgr;
|
||||
|
||||
@ -551,15 +552,22 @@ static HRESULT WINAPI RemUnknown_RemQueryInterface(IRemUnknown *iface,
|
||||
|
||||
for (i = 0; i < cIids; i++)
|
||||
{
|
||||
(*ppQIResults)[i].hResult = register_ifstub(apt, &(*ppQIResults)[i].std,
|
||||
&iids[i], stubmgr->object,
|
||||
MSHLFLAGS_NORMAL);
|
||||
HRESULT hrobj = register_ifstub(apt, &(*ppQIResults)[i].std, &iids[i],
|
||||
stubmgr->object, MSHLFLAGS_NORMAL);
|
||||
if (hrobj == S_OK)
|
||||
successful_qis++;
|
||||
(*ppQIResults)[i].hResult = hrobj;
|
||||
}
|
||||
|
||||
stub_manager_int_release(stubmgr);
|
||||
COM_ApartmentRelease(apt);
|
||||
|
||||
return hr;
|
||||
if (successful_qis == cIids)
|
||||
return S_OK; /* we got all requested interfaces */
|
||||
else if (successful_qis == 0)
|
||||
return E_NOINTERFACE; /* we didn't get any interfaces */
|
||||
else
|
||||
return S_FALSE; /* we got some interfaces */
|
||||
}
|
||||
|
||||
static HRESULT WINAPI RemUnknown_RemAddRef(IRemUnknown *iface,
|
||||
|
@ -876,7 +876,7 @@ static void test_proxy_interfaces()
|
||||
if (hr == S_OK) IUnknown_Release(pOtherUnknown);
|
||||
|
||||
hr = IUnknown_QueryInterface(pProxy, &IID_IMultiQI, (LPVOID*)&pOtherUnknown);
|
||||
todo_wine { ok_ole_success(hr, IUnknown_QueryInterface IID_IMultiQI); }
|
||||
ok_ole_success(hr, IUnknown_QueryInterface IID_IMultiQI);
|
||||
if (hr == S_OK) IUnknown_Release(pOtherUnknown);
|
||||
|
||||
hr = IUnknown_QueryInterface(pProxy, &IID_IMarshal, (LPVOID*)&pOtherUnknown);
|
||||
|
Loading…
x
Reference in New Issue
Block a user