From 14a879085e415c4242819cb0638f60cd317c0a23 Mon Sep 17 00:00:00 2001 From: Huw Davies Date: Thu, 24 Oct 2013 16:16:47 +0100 Subject: [PATCH] ole32/tests: Extend the lifecycle tests to objects which expose IExternalConnection. --- dlls/ole32/tests/marshal.c | 236 +++++++++++++++++++++++++++++++------ 1 file changed, 201 insertions(+), 35 deletions(-) diff --git a/dlls/ole32/tests/marshal.c b/dlls/ole32/tests/marshal.c index 95dae0a7c92..48f3ceae591 100644 --- a/dlls/ole32/tests/marshal.c +++ b/dlls/ole32/tests/marshal.c @@ -46,6 +46,9 @@ static HRESULT (WINAPI *pDllGetClassObject)(REFCLSID,REFIID,LPVOID); #define ok_more_than_one_lock() ok(cLocks > 0, "Number of locks should be > 0, but actually is %d\n", cLocks) #define ok_no_locks() ok(cLocks == 0, "Number of locks should be 0, but actually is %d\n", cLocks) #define ok_ole_success(hr, func) ok(hr == S_OK, #func " failed with error 0x%08x\n", hr) +#define ok_non_zero_external_conn() do {if (with_external_conn) ok(external_connections, "got no external connections\n");} while(0); +#define ok_zero_external_conn() do {if (with_external_conn) ok(!external_connections, "got %d external connections\n", external_connections);} while(0); +#define ok_last_release_closes(b) do {if (with_external_conn) ok(last_release_closes == b, "got %d expected %d\n", last_release_closes, b);} while(0); static const IID IID_IWineTest = { @@ -382,6 +385,7 @@ static void test_normal_marshal_and_release(void) IStream *pStream = NULL; cLocks = 0; + external_connections = 0; hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream); ok_ole_success(hr, CreateStreamOnHGlobal); @@ -389,6 +393,7 @@ static void test_normal_marshal_and_release(void) ok_ole_success(hr, CoMarshalInterface); ok_more_than_one_lock(); + ok_non_zero_external_conn(); IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); hr = CoReleaseMarshalData(pStream); @@ -396,6 +401,8 @@ static void test_normal_marshal_and_release(void) IStream_Release(pStream); ok_no_locks(); + ok_zero_external_conn(); + ok_last_release_closes(TRUE); } /* tests success case of a same-thread marshal and unmarshal */ @@ -406,6 +413,7 @@ static void test_normal_marshal_and_unmarshal(void) IUnknown *pProxy = NULL; cLocks = 0; + external_connections = 0; hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream); ok_ole_success(hr, CreateStreamOnHGlobal); @@ -413,6 +421,7 @@ static void test_normal_marshal_and_unmarshal(void) ok_ole_success(hr, CoMarshalInterface); ok_more_than_one_lock(); + ok_non_zero_external_conn(); IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy); @@ -420,6 +429,9 @@ static void test_normal_marshal_and_unmarshal(void) IStream_Release(pStream); ok_more_than_one_lock(); + ok_zero_external_conn(); +todo_wine + ok_last_release_closes(FALSE); IUnknown_Release(pProxy); @@ -437,18 +449,22 @@ static void test_marshal_and_unmarshal_invalid(void) HANDLE thread; cLocks = 0; + external_connections = 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(); - + ok_non_zero_external_conn(); + IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); hr = CoReleaseMarshalData(pStream); ok_ole_success(hr, CoReleaseMarshalData); ok_no_locks(); + ok_zero_external_conn(); + ok_last_release_closes(TRUE); IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy); @@ -477,6 +493,7 @@ static void test_same_apartment_unmarshal_failure(void) static const LARGE_INTEGER llZero; cLocks = 0; + external_connections = 0; hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream); ok_ole_success(hr, CreateStreamOnHGlobal); @@ -485,6 +502,7 @@ static void test_same_apartment_unmarshal_failure(void) ok_ole_success(hr, CoMarshalInterface); ok_more_than_one_lock(); + ok_non_zero_external_conn(); hr = IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL); ok_ole_success(hr, IStream_Seek); @@ -493,6 +511,9 @@ static void test_same_apartment_unmarshal_failure(void) ok(hr == E_NOINTERFACE, "CoUnmarshalInterface should have returned E_NOINTERFACE instead of 0x%08x\n", hr); ok_no_locks(); + ok_zero_external_conn(); +todo_wine + ok_last_release_closes(FALSE); IStream_Release(pStream); } @@ -507,12 +528,14 @@ static void test_interthread_marshal_and_unmarshal(void) HANDLE thread; cLocks = 0; + external_connections = 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(); + ok_non_zero_external_conn(); IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy); @@ -520,10 +543,13 @@ static void test_interthread_marshal_and_unmarshal(void) IStream_Release(pStream); ok_more_than_one_lock(); + ok_non_zero_external_conn(); IUnknown_Release(pProxy); ok_no_locks(); + ok_zero_external_conn(); + ok_last_release_closes(TRUE); end_host_object(tid, thread); } @@ -544,12 +570,14 @@ static void test_proxy_marshal_and_unmarshal(void) int i; cLocks = 0; + external_connections = 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(); + ok_non_zero_external_conn(); IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy); @@ -582,6 +610,7 @@ static void test_proxy_marshal_and_unmarshal(void) ok_ole_success(hr, CoUnmarshalInterface); ok_more_than_one_lock(); + ok_non_zero_external_conn(); IUnknown_Release(pProxy2); @@ -595,6 +624,8 @@ static void test_proxy_marshal_and_unmarshal(void) } ok_no_locks(); + ok_zero_external_conn(); + ok_last_release_closes(TRUE); IStream_Release(pStream); @@ -613,12 +644,14 @@ static void test_proxy_marshal_and_unmarshal2(void) HANDLE thread; cLocks = 0; + external_connections = 0; hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream); ok_ole_success(hr, CreateStreamOnHGlobal); tid = start_host_object(pStream, &IID_IUnknown, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread); ok_more_than_one_lock(); + ok_non_zero_external_conn(); IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); hr = CoUnmarshalInterface(pStream, &IID_IUnknown, (void **)&pProxy); @@ -653,10 +686,13 @@ static void test_proxy_marshal_and_unmarshal2(void) IUnknown_Release(pProxy); ok_more_than_one_lock(); + ok_non_zero_external_conn(); IUnknown_Release(pProxy2); ok_no_locks(); + ok_zero_external_conn(); + ok_last_release_closes(TRUE); end_host_object(tid, thread); } @@ -672,18 +708,21 @@ static void test_proxy_marshal_and_unmarshal_weak(void) HANDLE thread; cLocks = 0; + external_connections = 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(); + ok_non_zero_external_conn(); 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(); + ok_non_zero_external_conn(); IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); /* marshal the proxy */ @@ -691,6 +730,7 @@ static void test_proxy_marshal_and_unmarshal_weak(void) ok_ole_success(hr, CoMarshalInterface); ok_more_than_one_lock(); + ok_non_zero_external_conn(); /* release the original proxy to test that we successfully keep the * original object alive */ @@ -702,6 +742,8 @@ static void test_proxy_marshal_and_unmarshal_weak(void) ok(hr == CO_E_OBJNOTREG, "CoUnmarshalInterface should return CO_E_OBJNOTREG instead of 0x%08x\n", hr); ok_no_locks(); + ok_zero_external_conn(); + ok_last_release_closes(TRUE); IStream_Release(pStream); @@ -719,18 +761,21 @@ static void test_proxy_marshal_and_unmarshal_strong(void) HANDLE thread; cLocks = 0; + external_connections = 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(); + ok_non_zero_external_conn(); 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(); + ok_non_zero_external_conn(); IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); /* marshal the proxy */ @@ -744,6 +789,7 @@ static void test_proxy_marshal_and_unmarshal_strong(void) } ok_more_than_one_lock(); + ok_non_zero_external_conn(); /* release the original proxy to test that we successfully keep the * original object alive */ @@ -754,10 +800,12 @@ static void test_proxy_marshal_and_unmarshal_strong(void) ok_ole_success(hr, CoUnmarshalInterface); ok_more_than_one_lock(); + ok_non_zero_external_conn(); IUnknown_Release(pProxy2); ok_more_than_one_lock(); + ok_non_zero_external_conn(); end: IStream_Release(pStream); @@ -765,6 +813,10 @@ end: end_host_object(tid, thread); ok_no_locks(); +todo_wine { + ok_zero_external_conn(); + ok_last_release_closes(FALSE); +} } /* tests that stubs are released when the containing apartment is destroyed */ @@ -777,12 +829,14 @@ static void test_marshal_stub_apartment_shutdown(void) HANDLE thread; cLocks = 0; + external_connections = 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(); + ok_non_zero_external_conn(); IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy); @@ -790,10 +844,15 @@ static void test_marshal_stub_apartment_shutdown(void) IStream_Release(pStream); ok_more_than_one_lock(); + ok_non_zero_external_conn(); end_host_object(tid, thread); ok_no_locks(); +todo_wine { + ok_zero_external_conn(); + ok_last_release_closes(FALSE); +} IUnknown_Release(pProxy); @@ -810,12 +869,14 @@ static void test_marshal_proxy_apartment_shutdown(void) HANDLE thread; cLocks = 0; + external_connections = 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(); + ok_non_zero_external_conn(); IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy); @@ -823,10 +884,13 @@ static void test_marshal_proxy_apartment_shutdown(void) IStream_Release(pStream); ok_more_than_one_lock(); + ok_non_zero_external_conn(); CoUninitialize(); ok_no_locks(); + ok_zero_external_conn(); + ok_last_release_closes(TRUE); IUnknown_Release(pProxy); @@ -850,12 +914,14 @@ static void test_marshal_proxy_mta_apartment_shutdown(void) pCoInitializeEx(NULL, COINIT_MULTITHREADED); cLocks = 0; + external_connections = 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(); + ok_non_zero_external_conn(); IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy); @@ -863,10 +929,13 @@ static void test_marshal_proxy_mta_apartment_shutdown(void) IStream_Release(pStream); ok_more_than_one_lock(); + ok_non_zero_external_conn(); CoUninitialize(); ok_no_locks(); + ok_zero_external_conn(); + ok_last_release_closes(TRUE); IUnknown_Release(pProxy); @@ -916,6 +985,7 @@ static void test_no_couninitialize_server(void) struct ncu_params ncu_params; cLocks = 0; + external_connections = 0; ncu_params.marshal_event = CreateEventA(NULL, TRUE, FALSE, NULL); ncu_params.unmarshal_event = CreateEventA(NULL, TRUE, FALSE, NULL); @@ -928,6 +998,7 @@ static void test_no_couninitialize_server(void) ok( !WaitForSingleObject(ncu_params.marshal_event, 10000), "wait timed out\n" ); ok_more_than_one_lock(); + ok_non_zero_external_conn(); IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy); @@ -935,11 +1006,16 @@ static void test_no_couninitialize_server(void) IStream_Release(pStream); ok_more_than_one_lock(); + ok_non_zero_external_conn(); SetEvent(ncu_params.unmarshal_event); ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" ); ok_no_locks(); +todo_wine { + ok_zero_external_conn(); + ok_last_release_closes(FALSE); +} CloseHandle(thread); CloseHandle(ncu_params.marshal_event); @@ -982,6 +1058,7 @@ static void test_no_couninitialize_client(void) struct ncu_params ncu_params; cLocks = 0; + external_connections = 0; hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream); ok_ole_success(hr, CreateStreamOnHGlobal); @@ -993,6 +1070,7 @@ static void test_no_couninitialize_client(void) IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); ok_more_than_one_lock(); + ok_non_zero_external_conn(); thread = CreateThread(NULL, 0, no_couninitialize_client_proc, &ncu_params, 0, &tid); @@ -1000,6 +1078,8 @@ static void test_no_couninitialize_client(void) CloseHandle(thread); ok_no_locks(); + ok_zero_external_conn(); + ok_last_release_closes(TRUE); end_host_object(host_tid, host_thread); } @@ -1015,34 +1095,49 @@ static void test_tableweak_marshal_and_unmarshal_twice(void) HANDLE thread; cLocks = 0; + external_connections = 0; hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream); ok_ole_success(hr, CreateStreamOnHGlobal); tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_TABLEWEAK, &thread); ok_more_than_one_lock(); + ok_zero_external_conn(); IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy1); ok_ole_success(hr, CoUnmarshalInterface); ok_more_than_one_lock(); + ok_non_zero_external_conn(); IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2); - IStream_Release(pStream); ok_ole_success(hr, CoUnmarshalInterface); ok_more_than_one_lock(); IUnknown_Release(pProxy1); + ok_non_zero_external_conn(); IUnknown_Release(pProxy2); + ok_zero_external_conn(); + ok_last_release_closes(TRUE); - /* this line is shows the difference between weak and strong table marshaling: - * weak has cLocks == 0 - * strong has cLocks > 0 */ + /* When IExternalConnection is present COM's lifetime management + * behaviour is altered; the remaining weak ref prevents stub shutdown. */ + if (with_external_conn) + { +todo_wine + ok_more_than_one_lock(); + IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); + release_host_object(tid); + } + + /* Without IExternalConnection this line is shows the difference between weak and strong table marshaling + * weak has cLocks == 0, strong has cLocks > 0. */ ok_no_locks(); + IStream_Release(pStream); end_host_object(tid, thread); } @@ -1057,18 +1152,21 @@ static void test_tableweak_marshal_releasedata1(void) HANDLE thread; cLocks = 0; + external_connections = 0; hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream); ok_ole_success(hr, CreateStreamOnHGlobal); tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_TABLEWEAK, &thread); ok_more_than_one_lock(); + ok_zero_external_conn(); IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy1); ok_ole_success(hr, CoUnmarshalInterface); ok_more_than_one_lock(); + ok_non_zero_external_conn(); /* release the remaining reference on the object by calling * CoReleaseMarshalData in the hosting thread */ @@ -1076,6 +1174,7 @@ static void test_tableweak_marshal_releasedata1(void) release_host_object(tid); ok_more_than_one_lock(); + ok_non_zero_external_conn(); IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2); @@ -1083,15 +1182,22 @@ static void test_tableweak_marshal_releasedata1(void) IStream_Release(pStream); ok_more_than_one_lock(); + ok_non_zero_external_conn(); IUnknown_Release(pProxy1); + if (pProxy2) + { + ok_non_zero_external_conn(); IUnknown_Release(pProxy2); + } /* this line is shows the difference between weak and strong table marshaling: * weak has cLocks == 0 * strong has cLocks > 0 */ ok_no_locks(); + ok_zero_external_conn(); + ok_last_release_closes(TRUE); end_host_object(tid, thread); } @@ -1106,12 +1212,14 @@ static void test_tableweak_marshal_releasedata2(void) HANDLE thread; cLocks = 0; + external_connections = 0; hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream); ok_ole_success(hr, CreateStreamOnHGlobal); tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_TABLEWEAK, &thread); ok_more_than_one_lock(); + ok_zero_external_conn(); /* release the remaining reference on the object by calling * CoReleaseMarshalData in the hosting thread */ @@ -1131,6 +1239,7 @@ static void test_tableweak_marshal_releasedata2(void) IStream_Release(pStream); ok_no_locks(); + ok_zero_external_conn(); end_host_object(tid, thread); } @@ -1166,7 +1275,15 @@ static DWORD CALLBACK weak_and_normal_marshal_thread_proc(void *p) while (WAIT_OBJECT_0 + 1 == MsgWaitForMultipleObjects(1, &hQuitEvent, FALSE, 10000, QS_ALLINPUT)) { while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) - DispatchMessageA(&msg); + { + if (msg.hwnd == NULL && msg.message == RELEASEMARSHALDATA) + { + CoReleaseMarshalData(data->pStreamWeak); + SetEvent((HANDLE)msg.lParam); + } + else + DispatchMessageA(&msg); + } } CloseHandle(hQuitEvent); @@ -1186,6 +1303,7 @@ static void test_tableweak_and_normal_marshal_and_unmarshal(void) struct weak_and_normal_marshal_data data; cLocks = 0; + external_connections = 0; data.hReadyEvent = CreateEventA(NULL, FALSE, FALSE, NULL); data.hQuitEvent = CreateEventA(NULL, FALSE, FALSE, NULL); @@ -1199,6 +1317,7 @@ static void test_tableweak_and_normal_marshal_and_unmarshal(void) CloseHandle(data.hReadyEvent); ok_more_than_one_lock(); + ok_non_zero_external_conn(); IStream_Seek(data.pStreamWeak, ullZero, STREAM_SEEK_SET, NULL); hr = CoUnmarshalInterface(data.pStreamWeak, &IID_IClassFactory, (void **)&pProxyWeak); @@ -1215,9 +1334,22 @@ static void test_tableweak_and_normal_marshal_and_unmarshal(void) IUnknown_Release(pProxyNormal); ok_more_than_one_lock(); + ok_non_zero_external_conn(); IUnknown_Release(pProxyWeak); + ok_zero_external_conn(); + ok_last_release_closes(TRUE); + + /* When IExternalConnection is present COM's lifetime management + * behaviour is altered; the remaining weak ref prevents stub shutdown. */ + if (with_external_conn) + { +todo_wine + ok_more_than_one_lock(); + IStream_Seek(data.pStreamWeak, ullZero, STREAM_SEEK_SET, NULL); + release_host_object(tid); + } ok_no_locks(); IStream_Release(data.pStreamWeak); @@ -1239,12 +1371,14 @@ static void test_tablestrong_marshal_and_unmarshal_twice(void) HANDLE thread; cLocks = 0; + external_connections = 0; hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream); ok_ole_success(hr, CreateStreamOnHGlobal); tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_TABLESTRONG, &thread); ok_more_than_one_lock(); + ok_non_zero_external_conn(); IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy1); @@ -1273,6 +1407,8 @@ static void test_tablestrong_marshal_and_unmarshal_twice(void) IStream_Release(pStream); ok_no_locks(); + ok_zero_external_conn(); + ok_last_release_closes(TRUE); end_host_object(tid, thread); } @@ -1284,17 +1420,20 @@ static void test_lock_object_external(void) IStream *pStream = NULL; cLocks = 0; - with_external_conn = TRUE; + external_connections = 0; /* test the stub manager creation aspect of CoLockObjectExternal when the * object hasn't been marshaled yet */ CoLockObjectExternal((IUnknown*)&Test_ClassFactory, TRUE, TRUE); ok_more_than_one_lock(); + ok_non_zero_external_conn(); CoDisconnectObject((IUnknown*)&Test_ClassFactory, 0); ok_no_locks(); + ok_non_zero_external_conn(); + external_connections = 0; /* test our empty stub manager being handled correctly in * CoMarshalInterface */ @@ -1308,6 +1447,7 @@ static void test_lock_object_external(void) CoLockObjectExternal((IUnknown*)&Test_ClassFactory, TRUE, TRUE); ok_more_than_one_lock(); + ok_non_zero_external_conn(); IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); hr = CoReleaseMarshalData(pStream); @@ -1315,15 +1455,20 @@ static void test_lock_object_external(void) IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); ok_more_than_one_lock(); + ok_non_zero_external_conn(); + ok_last_release_closes(TRUE); CoLockObjectExternal((IUnknown*)&Test_ClassFactory, FALSE, TRUE); ok_more_than_one_lock(); + ok_non_zero_external_conn(); + ok_last_release_closes(TRUE); CoLockObjectExternal((IUnknown*)&Test_ClassFactory, FALSE, TRUE); ok_no_locks(); - ok(last_release_closes, "last_release_closes FALSE\n"); + ok_zero_external_conn(); + ok_last_release_closes(TRUE); /* test CoLockObjectExternal releases reference to object with * fLastUnlockReleases as TRUE and there are only strong references on @@ -1331,12 +1476,14 @@ static void test_lock_object_external(void) CoLockObjectExternal((IUnknown*)&Test_ClassFactory, TRUE, FALSE); ok_more_than_one_lock(); + ok_non_zero_external_conn(); CoLockObjectExternal((IUnknown*)&Test_ClassFactory, FALSE, FALSE); ok_no_locks(); + ok_zero_external_conn(); todo_wine - ok(!last_release_closes, "last_release_closes TRUE\n"); + ok_last_release_closes(FALSE); /* test CoLockObjectExternal doesn't release the last reference to an * object with fLastUnlockReleases as TRUE and there is a weak reference @@ -1345,23 +1492,25 @@ todo_wine ok_ole_success(hr, CoMarshalInterface); ok_more_than_one_lock(); + ok_zero_external_conn(); CoLockObjectExternal((IUnknown*)&Test_ClassFactory, TRUE, FALSE); ok_more_than_one_lock(); + ok_non_zero_external_conn(); CoLockObjectExternal((IUnknown*)&Test_ClassFactory, FALSE, FALSE); ok_more_than_one_lock(); + ok_zero_external_conn(); +todo_wine + ok_last_release_closes(FALSE); CoDisconnectObject((IUnknown*)&Test_ClassFactory, 0); ok_no_locks(); -todo_wine - ok(!last_release_closes, "last_release_closes TRUE\n"); IStream_Release(pStream); - with_external_conn = FALSE; } /* tests disconnecting stubs */ @@ -1371,15 +1520,19 @@ static void test_disconnect_stub(void) IStream *pStream = NULL; cLocks = 0; + external_connections = 0; hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream); ok_ole_success(hr, CreateStreamOnHGlobal); hr = CoMarshalInterface(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL); ok_ole_success(hr, CoMarshalInterface); + ok_non_zero_external_conn(); + CoLockObjectExternal((IUnknown*)&Test_ClassFactory, TRUE, TRUE); ok_more_than_one_lock(); + ok_non_zero_external_conn(); IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); hr = CoReleaseMarshalData(pStream); @@ -1387,10 +1540,12 @@ static void test_disconnect_stub(void) IStream_Release(pStream); ok_more_than_one_lock(); + ok_non_zero_external_conn(); CoDisconnectObject((IUnknown*)&Test_ClassFactory, 0); ok_no_locks(); + ok_non_zero_external_conn(); hr = CoDisconnectObject(NULL, 0); ok( hr == E_INVALIDARG, "wrong status %x\n", hr ); @@ -1405,6 +1560,7 @@ static void test_normal_marshal_and_unmarshal_twice(void) IUnknown *pProxy2 = NULL; cLocks = 0; + external_connections = 0; hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream); ok_ole_success(hr, CreateStreamOnHGlobal); @@ -1412,12 +1568,16 @@ static void test_normal_marshal_and_unmarshal_twice(void) ok_ole_success(hr, CoMarshalInterface); ok_more_than_one_lock(); + ok_non_zero_external_conn(); IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy1); ok_ole_success(hr, CoUnmarshalInterface); ok_more_than_one_lock(); + ok_zero_external_conn(); +todo_wine + ok_last_release_closes(FALSE); IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2); @@ -3250,29 +3410,35 @@ START_TEST(marshal) /* FIXME: test CoCreateInstanceEx */ /* lifecycle management and marshaling tests */ - test_no_marshaler(); - test_normal_marshal_and_release(); - test_normal_marshal_and_unmarshal(); - test_marshal_and_unmarshal_invalid(); - test_same_apartment_unmarshal_failure(); - 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(); - test_no_couninitialize_server(); - test_no_couninitialize_client(); - test_tableweak_marshal_and_unmarshal_twice(); - test_tableweak_marshal_releasedata1(); - test_tableweak_marshal_releasedata2(); - test_tableweak_and_normal_marshal_and_unmarshal(); - test_tablestrong_marshal_and_unmarshal_twice(); - test_lock_object_external(); - test_disconnect_stub(); - test_normal_marshal_and_unmarshal_twice(); + do + { + test_no_marshaler(); + test_normal_marshal_and_release(); + test_normal_marshal_and_unmarshal(); + test_marshal_and_unmarshal_invalid(); + test_same_apartment_unmarshal_failure(); + 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(); + test_no_couninitialize_server(); + test_no_couninitialize_client(); + test_tableweak_marshal_and_unmarshal_twice(); + test_tableweak_marshal_releasedata1(); + test_tableweak_marshal_releasedata2(); + test_tableweak_and_normal_marshal_and_unmarshal(); + test_tablestrong_marshal_and_unmarshal_twice(); + test_lock_object_external(); + test_disconnect_stub(); + test_normal_marshal_and_unmarshal_twice(); + + with_external_conn = !with_external_conn; + } while (with_external_conn); + test_hresult_marshaling(); test_proxy_used_in_wrong_thread(); test_message_filter();