Rob Shearman : ole32: The identity functions can be used from apartments other than the one the proxy was unmarshaled into .

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


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

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

ole32: The identity functions can be used from apartments other than the one the proxy was unmarshaled into.

In this case, don't use the cached This->remunk and don't cache the 
unmarshaled object in This->remunk.

---

 dlls/ole32/marshal.c       |   19 +++++++++++++++----
 dlls/ole32/tests/marshal.c |   38 +++++++++++++++++++++++++++++++++++++-
 2 files changed, 52 insertions(+), 5 deletions(-)

diff --git a/dlls/ole32/marshal.c b/dlls/ole32/marshal.c
index 9c7d53c..d918347 100644
--- a/dlls/ole32/marshal.c
+++ b/dlls/ole32/marshal.c
@@ -298,7 +298,7 @@ static HRESULT WINAPI ClientIdentity_QueryMultipleInterfaces(IMultiQI *iface, UL
                 ULONG index = mapping[i];
                 HRESULT hrobj = qiresults[i].hResult;
                 if (hrobj == S_OK)
-                    hrobj = unmarshal_object(&qiresults[i].std, This->parent,
+                    hrobj = unmarshal_object(&qiresults[i].std, COM_CurrentApt(),
                                              This->dest_context,
                                              This->dest_context_data,
                                              pMQIs[index].pIID, &This->oxid_info,
@@ -964,14 +964,25 @@ static void proxy_manager_disconnect(struct proxy_manager * This)
 static HRESULT proxy_manager_get_remunknown(struct proxy_manager * This, IRemUnknown **remunk)
 {
     HRESULT hr = S_OK;
+    struct apartment *apt;
+    BOOL called_in_original_apt;
 
     /* we don't want to try and unmarshal or use IRemUnknown if we don't want
      * lifetime management */
     if (This->sorflags & SORFP_NOLIFETIMEMGMT)
         return S_FALSE;
 
+    apt = COM_CurrentApt();
+    if (!apt)
+        return CO_E_NOTINITIALIZED;
+
+    called_in_original_apt = This->parent && (This->parent->oxid == apt->oxid);
+
     EnterCriticalSection(&This->cs);
-    if (This->remunk)
+    /* only return the cached object if called from the original apartment.
+     * in future, we might want to make the IRemUnknown proxy callable from any
+     * apartment to avoid these checks */
+    if (This->remunk && called_in_original_apt)
     {
         /* already created - return existing object */
         *remunk = This->remunk;
@@ -994,10 +1005,10 @@ static HRESULT proxy_manager_get_remunknown(struct proxy_manager * This, IRemUnk
         stdobjref.ipid = This->oxid_info.ipidRemUnknown;
 
         /* do the unmarshal */
-        hr = unmarshal_object(&stdobjref, This->parent, This->dest_context,
+        hr = unmarshal_object(&stdobjref, COM_CurrentApt(), This->dest_context,
                               This->dest_context_data, &IID_IRemUnknown,
                               &This->oxid_info, (void**)remunk);
-        if (hr == S_OK)
+        if (hr == S_OK && called_in_original_apt)
         {
             This->remunk = *remunk;
             IRemUnknown_AddRef(This->remunk);
diff --git a/dlls/ole32/tests/marshal.c b/dlls/ole32/tests/marshal.c
index 843b220..e64b9f5 100644
--- a/dlls/ole32/tests/marshal.c
+++ b/dlls/ole32/tests/marshal.c
@@ -1283,6 +1283,24 @@ static DWORD CALLBACK bad_thread_proc(LPVOID p)
     HRESULT hr;
     IUnknown * proxy = NULL;
 
+    hr = IClassFactory_CreateInstance(cf, NULL, &IID_IUnknown, (LPVOID*)&proxy);
+    todo_wine
+    ok(hr == CO_E_NOTINITIALIZED,
+       "COM should have failed with CO_E_NOTINITIALIZED on using proxy without apartment, but instead returned 0x%08x\n",
+       hr);
+
+    hr = IClassFactory_QueryInterface(cf, &IID_IMultiQI, (LPVOID *)&proxy);
+    /* Win9x returns S_OK, whilst NT returns RPC_E_WRONG_THREAD */
+    trace("call to proxy's QueryInterface for local interface without apartment returned 0x%08x\n", hr);
+    if (SUCCEEDED(hr))
+        IUnknown_Release(proxy);
+
+    hr = IClassFactory_QueryInterface(cf, &IID_IStream, (LPVOID *)&proxy);
+    /* Win9x returns E_NOINTERFACE, whilst NT returns RPC_E_WRONG_THREAD */
+    trace("call to proxy's QueryInterface without apartment returned 0x%08x\n", hr);
+    if (SUCCEEDED(hr))
+        IUnknown_Release(proxy);
+
     pCoInitializeEx(NULL, COINIT_MULTITHREADED);
 
     hr = IClassFactory_CreateInstance(cf, NULL, &IID_IUnknown, (LPVOID*)&proxy);
@@ -1291,6 +1309,19 @@ static DWORD CALLBACK bad_thread_proc(LPVOID p)
         "COM should have failed with RPC_E_WRONG_THREAD on using proxy from wrong apartment, but instead returned 0x%08x\n",
         hr);
 
+    hr = IClassFactory_QueryInterface(cf, &IID_IStream, (LPVOID *)&proxy);
+    /* Win9x returns E_NOINTERFACE, whilst NT returns RPC_E_WRONG_THREAD */
+    trace("call to proxy's QueryInterface from wrong apartment returned 0x%08x\n", hr);
+
+    /* this statement causes Win9x DCOM to crash during CoUninitialize of
+     * other apartment, so don't test this on Win9x (signified by NT-only
+     * export of CoRegisterSurrogateEx) */
+    if (GetProcAddress(GetModuleHandle("ole32"), "CoRegisterSurrogateEx"))
+        /* now be really bad and release the proxy from the wrong apartment */
+        IUnknown_Release(cf);
+    else
+        skip("skipping test for releasing proxy from wrong apartment that will succeed, but cause a crash during CoUninitialize\n");
+
     CoUninitialize();
 
     return 0;
@@ -1321,13 +1352,18 @@ static void test_proxy_used_in_wrong_thread(void)
 
     ok_more_than_one_lock();
 
+    /* do a call that will fail, but result in IRemUnknown being used by the proxy */
+    IClassFactory_QueryInterface(pProxy, &IID_IStream, (LPVOID *)&pStream);
+
     /* create a thread that we can misbehave in */
     thread = CreateThread(NULL, 0, bad_thread_proc, (LPVOID)pProxy, 0, &tid2);
 
     WaitForSingleObject(thread, INFINITE);
     CloseHandle(thread);
 
-    IUnknown_Release(pProxy);
+    /* do release statement on Win9x that we should have done above */
+    if (!GetProcAddress(GetModuleHandle("ole32"), "CoRegisterSurrogateEx"))
+        IUnknown_Release(pProxy);
 
     ok_no_locks();
 




More information about the wine-cvs mailing list