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