Rob Shearman : ole32: Handle MSHLFLAGS_TABLEWEAK and MSHLFLAGS_TABLESTRONG when marshaling a proxy .

Alexandre Julliard julliard at wine.codeweavers.com
Tue May 22 07:00:07 CDT 2007


Module: wine
Branch: master
Commit: 5369d4dffd97a78d3dc1b312b123cd7855c325c4
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=5369d4dffd97a78d3dc1b312b123cd7855c325c4

Author: Rob Shearman <rob at codeweavers.com>
Date:   Mon May 21 16:43:09 2007 +0100

ole32: Handle MSHLFLAGS_TABLEWEAK and MSHLFLAGS_TABLESTRONG when marshaling a proxy.

Add tests for this behaviour.

---

 dlls/ole32/marshal.c       |   44 +++++++++++-------
 dlls/ole32/tests/marshal.c |  108 ++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 136 insertions(+), 16 deletions(-)

diff --git a/dlls/ole32/marshal.c b/dlls/ole32/marshal.c
index 120361a..759a683 100644
--- a/dlls/ole32/marshal.c
+++ b/dlls/ole32/marshal.c
@@ -375,22 +375,29 @@ static HRESULT WINAPI Proxy_MarshalInterface(
     if (SUCCEEDED(hr))
     {
         STDOBJREF stdobjref = ifproxy->stdobjref;
-        ULONG cPublicRefs = ifproxy->refs;
-        ULONG cPublicRefsOld;
 
-        /* optimization - share out proxy's public references if possible
-         * instead of making new proxy do a roundtrip through the server */
-        do
+        stdobjref.cPublicRefs = 0;
+
+        if ((mshlflags != MSHLFLAGS_TABLEWEAK) &&
+            (mshlflags != MSHLFLAGS_TABLESTRONG))
         {
-            ULONG cPublicRefsNew;
-            cPublicRefsOld = cPublicRefs;
-            stdobjref.cPublicRefs = cPublicRefs / 2;
-            cPublicRefsNew = cPublicRefs - stdobjref.cPublicRefs;
-            cPublicRefs = InterlockedCompareExchange(
-                (LONG *)&ifproxy->refs, cPublicRefsNew, cPublicRefsOld);
-        } while (cPublicRefs != cPublicRefsOld);
-
-        if (!stdobjref.cPublicRefs)
+            ULONG cPublicRefs = ifproxy->refs;
+            ULONG cPublicRefsOld;
+            /* optimization - share out proxy's public references if possible
+             * instead of making new proxy do a roundtrip through the server */
+            do
+            {
+                ULONG cPublicRefsNew;
+                cPublicRefsOld = cPublicRefs;
+                stdobjref.cPublicRefs = cPublicRefs / 2;
+                cPublicRefsNew = cPublicRefs - stdobjref.cPublicRefs;
+                cPublicRefs = InterlockedCompareExchange(
+                    (LONG *)&ifproxy->refs, cPublicRefsNew, cPublicRefsOld);
+            } while (cPublicRefs != cPublicRefsOld);
+        }
+
+        /* normal and table-strong marshaling need at least one reference */
+        if (!stdobjref.cPublicRefs && (mshlflags != MSHLFLAGS_TABLEWEAK))
         {
             IRemUnknown *remunk;
             hr = proxy_manager_get_remunknown(This, &remunk);
@@ -399,11 +406,16 @@ static HRESULT WINAPI Proxy_MarshalInterface(
                 HRESULT hrref = S_OK;
                 REMINTERFACEREF rif;
                 rif.ipid = ifproxy->stdobjref.ipid;
-                rif.cPublicRefs = NORMALEXTREFS;
+                rif.cPublicRefs = (mshlflags == MSHLFLAGS_TABLESTRONG) ? 1 : NORMALEXTREFS;
                 rif.cPrivateRefs = 0;
                 hr = IRemUnknown_RemAddRef(remunk, 1, &rif, &hrref);
                 if (hr == S_OK && hrref == S_OK)
-                    stdobjref.cPublicRefs = rif.cPublicRefs;
+                {
+                    /* table-strong marshaling doesn't give the refs to the
+                     * client that unmarshals the STDOBJREF */
+                    if (mshlflags != MSHLFLAGS_TABLESTRONG)
+                        stdobjref.cPublicRefs = rif.cPublicRefs;
+                }
                 else
                     ERR("IRemUnknown_RemAddRef returned with 0x%08x, hrref = 0x%08x\n", hr, hrref);
             }
diff --git a/dlls/ole32/tests/marshal.c b/dlls/ole32/tests/marshal.c
index 2ad02ee..843b220 100644
--- a/dlls/ole32/tests/marshal.c
+++ b/dlls/ole32/tests/marshal.c
@@ -609,6 +609,112 @@ static void test_proxy_marshal_and_unmarshal2(void)
     end_host_object(tid, thread);
 }
 
+/* tests success case of an interthread marshal and then table-weak-marshaling the proxy */
+static void test_proxy_marshal_and_unmarshal_weak(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_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
+
+    ok_more_than_one_lock();
+
+    IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
+    hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (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_TABLEWEAK);
+    ok_ole_success(hr, CoMarshalInterface);
+
+    ok_more_than_one_lock();
+
+    /* release the original proxy to test that we successfully keep the
+     * original object alive */
+    IUnknown_Release(pProxy);
+
+    IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
+    hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2);
+    todo_wine
+    ok(hr == CO_E_OBJNOTREG, "CoUnmarshalInterface should return CO_E_OBJNOTREG instead of 0x%08x\n", hr);
+
+    ok_no_locks();
+
+    IStream_Release(pStream);
+
+    end_host_object(tid, thread);
+}
+
+/* tests success case of an interthread marshal and then table-strong-marshaling the proxy */
+static void test_proxy_marshal_and_unmarshal_strong(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_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
+
+    ok_more_than_one_lock();
+
+    IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
+    hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (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_TABLESTRONG);
+    ok(hr == S_OK /* WinNT */ || hr == E_INVALIDARG /* Win9x */,
+        "CoMarshalInterface should have return S_OK or E_INVALIDARG instead of 0x%08x\n", hr);
+    if (FAILED(hr))
+    {
+        IUnknown_Release(pProxy);
+        goto end;
+    }
+
+    ok_more_than_one_lock();
+
+    /* release the original proxy to test that we successfully keep the
+     * original object alive */
+    IUnknown_Release(pProxy);
+
+    IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
+    hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2);
+    ok_ole_success(hr, CoUnmarshalInterface);
+
+    ok_more_than_one_lock();
+
+    IUnknown_Release(pProxy2);
+
+    ok_more_than_one_lock();
+
+end:
+    IStream_Release(pStream);
+
+    end_host_object(tid, thread);
+
+    ok_no_locks();
+}
+
 /* tests that stubs are released when the containing apartment is destroyed */
 static void test_marshal_stub_apartment_shutdown(void)
 {
@@ -2750,6 +2856,8 @@ START_TEST(marshal)
     test_interthread_marshal_and_unmarshal();
     test_proxy_marshal_and_unmarshal();
     test_proxy_marshal_and_unmarshal2();
+    test_proxy_marshal_and_unmarshal_weak();
+    test_proxy_marshal_and_unmarshal_strong();
     test_marshal_stub_apartment_shutdown();
     test_marshal_proxy_apartment_shutdown();
     test_marshal_proxy_mta_apartment_shutdown();




More information about the wine-cvs mailing list