Robert Shearman : ole: Fix marshaling of proxies for interfaces that
haven' t already been unmarshaled.
Alexandre Julliard
julliard at wine.codeweavers.com
Thu Mar 2 05:17:32 CST 2006
Module: wine
Branch: refs/heads/master
Commit: 857a6d1f63001794ad6370abeab6f610b37f6a90
URL: http://source.winehq.org/git/?p=wine.git;a=commit;h=857a6d1f63001794ad6370abeab6f610b37f6a90
Author: Robert Shearman <rob at codeweavers.com>
Date: Wed Mar 1 12:18:14 2006 +0000
ole: Fix marshaling of proxies for interfaces that haven't already been unmarshaled.
---
dlls/ole32/marshal.c | 54 ++++++++++++++++++++++++++++++++-------
dlls/ole32/tests/marshal.c | 61 ++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 105 insertions(+), 10 deletions(-)
diff --git a/dlls/ole32/marshal.c b/dlls/ole32/marshal.c
index ef3df6e..aebdba1 100644
--- a/dlls/ole32/marshal.c
+++ b/dlls/ole32/marshal.c
@@ -366,25 +366,59 @@ static HRESULT WINAPI Proxy_MarshalInter
void* pvDestContext, DWORD mshlflags)
{
ICOM_THIS_MULTI(struct proxy_manager, lpVtblMarshal, iface);
- ULONG res;
HRESULT hr;
- STDOBJREF stdobjref;
struct ifproxy *ifproxy;
TRACE("(...,%s,...)\n", debugstr_guid(riid));
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);
- return hr;
+ STDOBJREF stdobjref = ifproxy->stdobjref;
+ /* 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 */
+
+ hr = IStream_Write(pStm, &stdobjref, sizeof(stdobjref), NULL);
}
+ else
+ {
+ /* 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);
- stdobjref = ifproxy->stdobjref;
- /* 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 */
- hr = IStream_Write(pStm, &stdobjref, sizeof(stdobjref), &res);
+ 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;
}
diff --git a/dlls/ole32/tests/marshal.c b/dlls/ole32/tests/marshal.c
index 10c690c..3de88a9 100644
--- a/dlls/ole32/tests/marshal.c
+++ b/dlls/ole32/tests/marshal.c
@@ -472,6 +472,66 @@ static void test_proxy_marshal_and_unmar
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 */
static void test_marshal_stub_apartment_shutdown(void)
{
@@ -1930,6 +1990,7 @@ START_TEST(marshal)
test_marshal_and_unmarshal_invalid();
test_interthread_marshal_and_unmarshal();
test_proxy_marshal_and_unmarshal();
+ test_proxy_marshal_and_unmarshal2();
test_marshal_stub_apartment_shutdown();
test_marshal_proxy_apartment_shutdown();
test_marshal_proxy_mta_apartment_shutdown();
More information about the wine-cvs
mailing list