Jacek Caban : ole32: Catch crashes in stub object destructors when destroying stub manager.

Alexandre Julliard julliard at wine.codeweavers.com
Wed Sep 2 10:23:16 CDT 2015


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

Author: Jacek Caban <jacek at codeweavers.com>
Date:   Wed Sep  2 11:21:16 2015 +0200

ole32: Catch crashes in stub object destructors when destroying stub manager.

---

 dlls/ole32/stubmanager.c   | 15 ++++++++-
 dlls/ole32/tests/marshal.c | 76 ++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 90 insertions(+), 1 deletion(-)

diff --git a/dlls/ole32/stubmanager.c b/dlls/ole32/stubmanager.c
index 3b9086d..668d46f 100644
--- a/dlls/ole32/stubmanager.c
+++ b/dlls/ole32/stubmanager.c
@@ -36,6 +36,8 @@
 #include "rpc.h"
 
 #include "wine/debug.h"
+#include "wine/exception.h"
+
 #include "compobj_private.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(ole);
@@ -254,7 +256,18 @@ static void stub_manager_delete(struct stub_manager *m)
         IExternalConnection_Release(m->extern_conn);
 
     CoTaskMemFree(m->oxid_info.psa);
-    IUnknown_Release(m->object);
+
+    /* Some broken apps crash in object destructors. We have a test showing
+     * that on winxp+ those crashes are caught and ignored. */
+    __TRY
+    {
+        IUnknown_Release(m->object);
+    }
+    __EXCEPT_PAGE_FAULT
+    {
+        ERR("Got page fault when releasing stub!\n");
+    }
+    __ENDTRY
 
     DEBUG_CLEAR_CRITSEC_NAME(&m->lock);
     DeleteCriticalSection(&m->lock);
diff --git a/dlls/ole32/tests/marshal.c b/dlls/ole32/tests/marshal.c
index a4006d0..55c32d6 100644
--- a/dlls/ole32/tests/marshal.c
+++ b/dlls/ole32/tests/marshal.c
@@ -195,6 +195,24 @@ static const IUnknownVtbl TestUnknown_Vtbl =
 
 static IUnknown Test_Unknown = { &TestUnknown_Vtbl };
 
+static ULONG WINAPI TestCrash_IUnknown_Release(LPUNKNOWN iface)
+{
+    UnlockModule();
+    if(!cLocks) {
+        trace("crashing...\n");
+        *(int**)0xc = 0;
+    }
+    return 1; /* non-heap-based object */
+}
+
+static const IUnknownVtbl TestCrashUnknown_Vtbl =
+{
+    Test_IUnknown_QueryInterface,
+    Test_IUnknown_AddRef,
+    TestCrash_IUnknown_Release,
+};
+
+static IUnknown TestCrash_Unknown = { &TestCrashUnknown_Vtbl };
 
 static HRESULT WINAPI Test_IClassFactory_QueryInterface(
     LPCLASSFACTORY iface,
@@ -1082,6 +1100,63 @@ static void test_no_couninitialize_client(void)
     end_host_object(host_tid, host_thread);
 }
 
+static BOOL crash_thread_success;
+
+static DWORD CALLBACK crash_couninitialize_proc(void *p)
+{
+    IStream *stream;
+    HRESULT hr;
+
+    cLocks = 0;
+
+    CoInitialize(NULL);
+
+    hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
+    ok_ole_success(hr, CreateStreamOnHGlobal);
+
+    hr = CoMarshalInterface(stream, &IID_IUnknown, &TestCrash_Unknown, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
+    ok_ole_success(hr, CoMarshalInterface);
+
+    IStream_Seek(stream, ullZero, STREAM_SEEK_SET, NULL);
+
+    hr = CoReleaseMarshalData(stream);
+    ok_ole_success(hr, CoReleaseMarshalData);
+
+    ok_no_locks();
+
+    hr = CoMarshalInterface(stream, &IID_IUnknown, &TestCrash_Unknown, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
+    ok_ole_success(hr, CoMarshalInterface);
+
+    ok_more_than_one_lock();
+
+    trace("CoUninitialize >>>\n");
+    CoUninitialize();
+    trace("CoUninitialize <<<\n");
+
+    ok_no_locks();
+
+    IStream_Release(stream);
+    crash_thread_success = TRUE;
+    return 0;
+}
+
+static void test_crash_couninitialize(void)
+{
+    HANDLE thread;
+    DWORD tid;
+
+    if(!GetProcAddress(GetModuleHandleA("kernel32.dll"), "CreateActCtxW")) {
+        win_skip("Skipping crash tests on win2k.\n");
+        return;
+    }
+
+    crash_thread_success = FALSE;
+    thread = CreateThread(NULL, 0, crash_couninitialize_proc, NULL, 0, &tid);
+    ok(!WaitForSingleObject(thread, 10000), "wait timed out\n");
+    CloseHandle(thread);
+    ok(crash_thread_success, "Crash thread failed\n");
+}
+
 /* tests success case of a same-thread table-weak marshal, unmarshal, unmarshal */
 static void test_tableweak_marshal_and_unmarshal_twice(void)
 {
@@ -3549,6 +3624,7 @@ START_TEST(marshal)
 
     test_globalinterfacetable();
     test_manualresetevent();
+    test_crash_couninitialize();
 
     /* must be last test as channel hooks can't be unregistered */
     test_channel_hook();




More information about the wine-cvs mailing list