mirror of
https://github.com/reactos/wine.git
synced 2025-02-17 03:18:32 +00:00
ole: Fix marshaling of proxies for interfaces that haven't already been unmarshaled.
This commit is contained in:
parent
269909f53e
commit
857a6d1f63
@ -366,25 +366,59 @@ static HRESULT WINAPI Proxy_MarshalInterface(
|
|||||||
void* pvDestContext, DWORD mshlflags)
|
void* pvDestContext, DWORD mshlflags)
|
||||||
{
|
{
|
||||||
ICOM_THIS_MULTI(struct proxy_manager, lpVtblMarshal, iface);
|
ICOM_THIS_MULTI(struct proxy_manager, lpVtblMarshal, iface);
|
||||||
ULONG res;
|
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
STDOBJREF stdobjref;
|
|
||||||
struct ifproxy *ifproxy;
|
struct ifproxy *ifproxy;
|
||||||
|
|
||||||
TRACE("(...,%s,...)\n", debugstr_guid(riid));
|
TRACE("(...,%s,...)\n", debugstr_guid(riid));
|
||||||
|
|
||||||
hr = proxy_manager_find_ifproxy(This, riid, &ifproxy);
|
hr = proxy_manager_find_ifproxy(This, riid, &ifproxy);
|
||||||
if (FAILED(hr))
|
if (SUCCEEDED(hr))
|
||||||
{
|
{
|
||||||
ERR("couldn't find proxy for interface %s, error 0x%08lx\n", debugstr_guid(riid), hr);
|
STDOBJREF stdobjref = ifproxy->stdobjref;
|
||||||
return hr;
|
/* FIXME: optimization - share out proxy's public references if possible
|
||||||
}
|
* instead of making new proxy do a roundtrip through the server */
|
||||||
|
stdobjref.cPublicRefs = 0; /* InterlockedDecrement(&This->stdobjref.cPublicRefs) >= 0 ? 1 : 0 */
|
||||||
|
|
||||||
stdobjref = ifproxy->stdobjref;
|
hr = IStream_Write(pStm, &stdobjref, sizeof(stdobjref), NULL);
|
||||||
/* FIXME: optimization - share out proxy's public references if possible
|
}
|
||||||
* instead of making new proxy do a roundtrip through the server */
|
else
|
||||||
stdobjref.cPublicRefs = 0; /* InterlockedDecrement(&This->stdobjref.cPublicRefs) >= 0 ? 1 : 0 */
|
{
|
||||||
hr = IStream_Write(pStm, &stdobjref, sizeof(stdobjref), &res);
|
/* we don't have the interface already unmarshaled so we have to
|
||||||
|
* request the object from the server */
|
||||||
|
IRemUnknown *remunk;
|
||||||
|
IPID *ipid;
|
||||||
|
REMQIRESULT *qiresults = NULL;
|
||||||
|
IID iid = *riid;
|
||||||
|
|
||||||
|
/* 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)->stdobjref.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,
|
||||||
|
1, &iid, &qiresults);
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
hr = IStream_Write(pStm, &qiresults->std, sizeof(qiresults->std), NULL);
|
||||||
|
if (FAILED(hr))
|
||||||
|
{
|
||||||
|
REMINTERFACEREF rif;
|
||||||
|
rif.ipid = qiresults->std.ipid;
|
||||||
|
rif.cPublicRefs = qiresults->std.cPublicRefs;
|
||||||
|
rif.cPrivateRefs = 0;
|
||||||
|
IRemUnknown_RemRelease(remunk, 1, &rif);
|
||||||
|
}
|
||||||
|
CoTaskMemFree(qiresults);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
ERR("IRemUnknown_RemQueryInterface failed with error 0x%08lx\n", hr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
@ -472,6 +472,66 @@ static void test_proxy_marshal_and_unmarshal(void)
|
|||||||
end_host_object(tid, thread);
|
end_host_object(tid, thread);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* tests success case of an interthread marshal and then marshaling the proxy
|
||||||
|
* using an iid that hasn't previously been unmarshaled */
|
||||||
|
static void test_proxy_marshal_and_unmarshal2(void)
|
||||||
|
{
|
||||||
|
HRESULT hr;
|
||||||
|
IStream *pStream = NULL;
|
||||||
|
IUnknown *pProxy = NULL;
|
||||||
|
IUnknown *pProxy2 = NULL;
|
||||||
|
DWORD tid;
|
||||||
|
HANDLE thread;
|
||||||
|
|
||||||
|
cLocks = 0;
|
||||||
|
|
||||||
|
hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
|
||||||
|
ok_ole_success(hr, CreateStreamOnHGlobal);
|
||||||
|
tid = start_host_object(pStream, &IID_IUnknown, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
|
||||||
|
|
||||||
|
ok_more_than_one_lock();
|
||||||
|
|
||||||
|
IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
|
||||||
|
hr = CoUnmarshalInterface(pStream, &IID_IUnknown, (void **)&pProxy);
|
||||||
|
ok_ole_success(hr, CoUnmarshalInterface);
|
||||||
|
|
||||||
|
ok_more_than_one_lock();
|
||||||
|
|
||||||
|
IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
|
||||||
|
/* marshal the proxy */
|
||||||
|
hr = CoMarshalInterface(pStream, &IID_IClassFactory, pProxy, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
|
||||||
|
ok_ole_success(hr, CoMarshalInterface);
|
||||||
|
|
||||||
|
ok_more_than_one_lock();
|
||||||
|
|
||||||
|
IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
|
||||||
|
/* unmarshal the second proxy to the object */
|
||||||
|
hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2);
|
||||||
|
ok_ole_success(hr, CoUnmarshalInterface);
|
||||||
|
IStream_Release(pStream);
|
||||||
|
|
||||||
|
/* now the proxies should be as follows:
|
||||||
|
* pProxy -> &Test_ClassFactory
|
||||||
|
* pProxy2 -> &Test_ClassFactory
|
||||||
|
* they should NOT be as follows:
|
||||||
|
* pProxy -> &Test_ClassFactory
|
||||||
|
* pProxy2 -> pProxy
|
||||||
|
* the above can only really be tested by looking in +ole traces
|
||||||
|
*/
|
||||||
|
|
||||||
|
ok_more_than_one_lock();
|
||||||
|
|
||||||
|
IUnknown_Release(pProxy);
|
||||||
|
|
||||||
|
ok_more_than_one_lock();
|
||||||
|
|
||||||
|
IUnknown_Release(pProxy2);
|
||||||
|
|
||||||
|
ok_no_locks();
|
||||||
|
|
||||||
|
end_host_object(tid, thread);
|
||||||
|
}
|
||||||
|
|
||||||
/* tests that stubs are released when the containing apartment is destroyed */
|
/* tests that stubs are released when the containing apartment is destroyed */
|
||||||
static void test_marshal_stub_apartment_shutdown(void)
|
static void test_marshal_stub_apartment_shutdown(void)
|
||||||
{
|
{
|
||||||
@ -1930,6 +1990,7 @@ START_TEST(marshal)
|
|||||||
test_marshal_and_unmarshal_invalid();
|
test_marshal_and_unmarshal_invalid();
|
||||||
test_interthread_marshal_and_unmarshal();
|
test_interthread_marshal_and_unmarshal();
|
||||||
test_proxy_marshal_and_unmarshal();
|
test_proxy_marshal_and_unmarshal();
|
||||||
|
test_proxy_marshal_and_unmarshal2();
|
||||||
test_marshal_stub_apartment_shutdown();
|
test_marshal_stub_apartment_shutdown();
|
||||||
test_marshal_proxy_apartment_shutdown();
|
test_marshal_proxy_apartment_shutdown();
|
||||||
test_marshal_proxy_mta_apartment_shutdown();
|
test_marshal_proxy_mta_apartment_shutdown();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user