ole32: Catch crashes in stub object destructors when destroying stub manager.
This commit is contained in:
parent
c784e34693
commit
cb183688bb
|
@ -36,6 +36,8 @@
|
||||||
#include "rpc.h"
|
#include "rpc.h"
|
||||||
|
|
||||||
#include "wine/debug.h"
|
#include "wine/debug.h"
|
||||||
|
#include "wine/exception.h"
|
||||||
|
|
||||||
#include "compobj_private.h"
|
#include "compobj_private.h"
|
||||||
|
|
||||||
WINE_DEFAULT_DEBUG_CHANNEL(ole);
|
WINE_DEFAULT_DEBUG_CHANNEL(ole);
|
||||||
|
@ -254,7 +256,18 @@ static void stub_manager_delete(struct stub_manager *m)
|
||||||
IExternalConnection_Release(m->extern_conn);
|
IExternalConnection_Release(m->extern_conn);
|
||||||
|
|
||||||
CoTaskMemFree(m->oxid_info.psa);
|
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);
|
DEBUG_CLEAR_CRITSEC_NAME(&m->lock);
|
||||||
DeleteCriticalSection(&m->lock);
|
DeleteCriticalSection(&m->lock);
|
||||||
|
|
|
@ -195,6 +195,24 @@ static const IUnknownVtbl TestUnknown_Vtbl =
|
||||||
|
|
||||||
static IUnknown Test_Unknown = { &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(
|
static HRESULT WINAPI Test_IClassFactory_QueryInterface(
|
||||||
LPCLASSFACTORY iface,
|
LPCLASSFACTORY iface,
|
||||||
|
@ -1082,6 +1100,63 @@ static void test_no_couninitialize_client(void)
|
||||||
end_host_object(host_tid, host_thread);
|
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 */
|
/* tests success case of a same-thread table-weak marshal, unmarshal, unmarshal */
|
||||||
static void test_tableweak_marshal_and_unmarshal_twice(void)
|
static void test_tableweak_marshal_and_unmarshal_twice(void)
|
||||||
{
|
{
|
||||||
|
@ -3549,6 +3624,7 @@ START_TEST(marshal)
|
||||||
|
|
||||||
test_globalinterfacetable();
|
test_globalinterfacetable();
|
||||||
test_manualresetevent();
|
test_manualresetevent();
|
||||||
|
test_crash_couninitialize();
|
||||||
|
|
||||||
/* must be last test as channel hooks can't be unregistered */
|
/* must be last test as channel hooks can't be unregistered */
|
||||||
test_channel_hook();
|
test_channel_hook();
|
||||||
|
|
Loading…
Reference in New Issue