Module: wine Branch: master Commit: e93c82e643b7b23489793a7410f31594ee72fa56 URL: http://source.winehq.org/git/wine.git/?a=commit;h=e93c82e643b7b23489793a7410... Author: Rob Shearman <rob(a)codeweavers.com> Date: Mon May 7 23:58:12 2007 +0100 ole32: Add tests for in-process registered class objects not being visible from different apartments. --- dlls/ole32/tests/compobj.c | 162 ++++++++++++++++++++++++++++++++++++++++++-- 1 files changed, 156 insertions(+), 6 deletions(-) diff --git a/dlls/ole32/tests/compobj.c b/dlls/ole32/tests/compobj.c index f07c95e..e568fb4 100644 --- a/dlls/ole32/tests/compobj.c +++ b/dlls/ole32/tests/compobj.c @@ -60,6 +60,12 @@ static const IID IID_IWineTest = 0x4fd0, {0xa1, 0xa2, 0x5d, 0x5a, 0x36, 0x54, 0xd3, 0xbd} }; /* 5201163f-8164-4fd0-a1a2-5d5a3654d3bd */ +static const CLSID CLSID_WineOOPTest = { + 0x5201163f, + 0x8164, + 0x4fd0, + {0xa1, 0xa2, 0x5d, 0x5a, 0x36, 0x54, 0xd3, 0xbd} +}; /* 5201163f-8164-4fd0-a1a2-5d5a3654d3bd */ static LONG cLocks; @@ -643,12 +649,6 @@ static void test_CoMarshalInterThreadInterfaceInStream(void) static void test_CoRegisterClassObject(void) { - static const CLSID CLSID_WineOOPTest = { - 0x5201163f, - 0x8164, - 0x4fd0, - {0xa1, 0xa2, 0x5d, 0x5a, 0x36, 0x54, 0xd3, 0xbd} - }; /* 5201163f-8164-4fd0-a1a2-5d5a3654d3bd */ DWORD cookie; HRESULT hr; IClassFactory *pcf; @@ -719,6 +719,155 @@ static void test_CoRegisterClassObject(void) CoUninitialize(); } +static HRESULT get_class_object(CLSCTX clsctx) +{ + HRESULT hr; + IClassFactory *pcf; + + hr = CoGetClassObject(&CLSID_WineOOPTest, clsctx, NULL, &IID_IClassFactory, + (void **)&pcf); + + if (SUCCEEDED(hr)) + IClassFactory_Release(pcf); + + return hr; +} + +static DWORD CALLBACK get_class_object_thread(LPVOID pv) +{ + CLSCTX clsctx = (CLSCTX)(DWORD_PTR)pv; + HRESULT hr; + + pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED); + + hr = get_class_object(clsctx); + + CoUninitialize(); + + return hr; +} + +static DWORD CALLBACK register_class_object_thread(LPVOID pv) +{ + HRESULT hr; + DWORD cookie; + + pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED); + + hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory, + CLSCTX_INPROC_SERVER, REGCLS_SINGLEUSE, &cookie); + + CoUninitialize(); + + return hr; +} + +static DWORD CALLBACK revoke_class_object_thread(LPVOID pv) +{ + DWORD cookie = (DWORD_PTR)pv; + HRESULT hr; + + pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED); + + hr = CoRevokeClassObject(cookie); + + CoUninitialize(); + + return hr; +} + +static void test_registered_object_thread_affinity(void) +{ + HRESULT hr; + DWORD cookie; + HANDLE thread; + DWORD tid; + DWORD exitcode; + + pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED); + + /* CLSCTX_INPROC_SERVER */ + + hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory, + CLSCTX_INPROC_SERVER, REGCLS_SINGLEUSE, &cookie); + ok_ole_success(hr, "CoRegisterClassObject"); + + thread = CreateThread(NULL, 0, get_class_object_thread, (LPVOID)CLSCTX_INPROC_SERVER, 0, &tid); + ok(thread != NULL, "CreateThread failed with error %d\n", GetLastError()); + WaitForSingleObject(thread, INFINITE); + GetExitCodeThread(thread, &exitcode); + hr = exitcode; + todo_wine + ok(hr == REGDB_E_CLASSNOTREG, "CoGetClassObject on inproc object " + "registered in different thread should return REGDB_E_CLASSNOTREG " + "instead of 0x%08x\n", hr); + + hr = get_class_object(CLSCTX_INPROC_SERVER); + ok(hr == S_OK, "CoGetClassObject on inproc object registered in same " + "thread should return S_OK instead of 0x%08x\n", hr); + + thread = CreateThread(NULL, 0, register_class_object_thread, NULL, 0, &tid); + ok(thread != NULL, "CreateThread failed with error %d\n", GetLastError()); + WaitForSingleObject(thread, INFINITE); + GetExitCodeThread(thread, &exitcode); + hr = exitcode; + todo_wine + ok(hr == S_OK, "CoRegisterClassObject with same CLSID but in different thread should return S_OK instead of 0x%08x\n", hr); + + hr = CoRevokeClassObject(cookie); + ok_ole_success(hr, "CoRevokeClassObject"); + + /* CLSCTX_LOCAL_SERVER */ + + hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory, + CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE, &cookie); + ok_ole_success(hr, "CoRegisterClassObject"); + + thread = CreateThread(NULL, 0, get_class_object_thread, (LPVOID)CLSCTX_LOCAL_SERVER, 0, &tid); + ok(thread != NULL, "CreateThread failed with error %d\n", GetLastError()); + while (MsgWaitForMultipleObjects(1, &thread, FALSE, INFINITE, QS_ALLINPUT) == WAIT_OBJECT_0 + 1) + { + MSG msg; + while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) + { + TranslateMessage(&msg); + DispatchMessageA(&msg); + } + } + GetExitCodeThread(thread, &exitcode); + hr = exitcode; + ok(hr == S_OK, "CoGetClassObject on local server object " + "registered in different thread should return S_OK " + "instead of 0x%08x\n", hr); + + hr = get_class_object(CLSCTX_LOCAL_SERVER); + ok(hr == S_OK, "CoGetClassObject on local server object registered in same " + "thread should return S_OK instead of 0x%08x\n", hr); + + thread = CreateThread(NULL, 0, revoke_class_object_thread, (LPVOID)cookie, 0, &tid); + ok(thread != NULL, "CreateThread failed with error %d\n", GetLastError()); + WaitForSingleObject(thread, INFINITE); + GetExitCodeThread(thread, &exitcode); + hr = exitcode; + todo_wine + ok(hr == RPC_E_WRONG_THREAD, "CoRevokeClassObject called from different " + "thread to where registered should return RPC_E_WRONG_THREAD instead of 0x%08x\n", hr); + + thread = CreateThread(NULL, 0, register_class_object_thread, NULL, 0, &tid); + ok(thread != NULL, "CreateThread failed with error %d\n", GetLastError()); + WaitForSingleObject(thread, INFINITE); + GetExitCodeThread(thread, &exitcode); + hr = exitcode; + ok(hr == S_OK, "CoRegisterClassObject with same CLSID but in different " + "thread should return S_OK instead of 0x%08x\n", hr); + + hr = CoRevokeClassObject(cookie); + todo_wine + ok_ole_success(hr, "CoRevokeClassObject"); + + CoUninitialize(); +} + static DWORD CALLBACK free_libraries_thread(LPVOID p) { CoFreeUnusedLibraries(); @@ -792,5 +941,6 @@ START_TEST(compobj) test_CoMarshalInterface(); test_CoMarshalInterThreadInterfaceInStream(); test_CoRegisterClassObject(); + test_registered_object_thread_affinity(); test_CoFreeUnusedLibraries(); }