Module: wine Branch: master Commit: 1dcf3f8e0a7969ffcc99b025aa1ec30837e0adba URL: http://source.winehq.org/git/wine.git/?a=commit;h=1dcf3f8e0a7969ffcc99b025aa... Author: Huw Davies <huw(a)codeweavers.com> Date: Tue Oct 13 14:49:16 2015 +0100 ole32/tests: Test calling CoDisconnectObject from within a COM call to the object. Signed-off-by: Huw Davies <huw(a)codeweavers.com> Signed-off-by: Alexandre Julliard <julliard(a)winehq.org> --- dlls/ole32/tests/marshal.c | 117 ++++++++++++++++++++++++++++++++++++++------- 1 file changed, 100 insertions(+), 17 deletions(-) diff --git a/dlls/ole32/tests/marshal.c b/dlls/ole32/tests/marshal.c index 55c32d6..afa58a5 100644 --- a/dlls/ole32/tests/marshal.c +++ b/dlls/ole32/tests/marshal.c @@ -2927,6 +2927,63 @@ static void UnlockModuleOOP(void) static HWND hwnd_app; +struct local_server +{ + IPersist IPersist_iface; /* a nice short interface */ +}; + +static HRESULT WINAPI local_server_QueryInterface(IPersist *iface, REFIID iid, void **obj) +{ + *obj = NULL; + + if (IsEqualGUID(iid, &IID_IUnknown) || + IsEqualGUID(iid, &IID_IPersist)) + *obj = iface; + + if (*obj) + { + IPersist_AddRef(iface); + return S_OK; + } + return E_NOINTERFACE; +} + +static ULONG WINAPI local_server_AddRef(IPersist *iface) +{ + return 2; +} + +static ULONG WINAPI local_server_Release(IPersist *iface) +{ + return 1; +} + +static HRESULT WINAPI local_server_GetClassID(IPersist *iface, CLSID *clsid) +{ + HRESULT hr; + + *clsid = IID_IUnknown; + + /* Test calling CoDisconnectObject within a COM call */ + hr = CoDisconnectObject((IUnknown *)iface, 0); + ok(hr == S_OK, "got %08x\n", hr); + + return S_OK; +} + +static const IPersistVtbl local_server_persist_vtbl = +{ + local_server_QueryInterface, + local_server_AddRef, + local_server_Release, + local_server_GetClassID +}; + +struct local_server local_server_class = +{ + {&local_server_persist_vtbl} +}; + static HRESULT WINAPI TestOOP_IClassFactory_QueryInterface( LPCLASSFACTORY iface, REFIID riid, @@ -2961,12 +3018,12 @@ static HRESULT WINAPI TestOOP_IClassFactory_CreateInstance( REFIID riid, LPVOID *ppvObj) { - if (IsEqualIID(riid, &IID_IClassFactory) || IsEqualIID(riid, &IID_IUnknown)) - { - *ppvObj = iface; - return S_OK; - } - return CLASS_E_CLASSNOTAVAILABLE; + IPersist *persist = &local_server_class.IPersist_iface; + HRESULT hr; + IPersist_AddRef( persist ); + hr = IPersist_QueryInterface( persist, riid, ppvObj ); + IPersist_Release( persist ); + return hr; } static HRESULT WINAPI TestOOP_IClassFactory_LockServer( @@ -2996,24 +3053,25 @@ static void test_register_local_server(void) DWORD cookie; HRESULT hr; HANDLE ready_event; - HANDLE quit_event; DWORD wait; + HANDLE handles[2]; heventShutdown = CreateEventA(NULL, TRUE, FALSE, NULL); + ready_event = CreateEventA(NULL, FALSE, FALSE, "Wine COM Test Ready Event"); + handles[0] = CreateEventA(NULL, FALSE, FALSE, "Wine COM Test Quit Event"); + handles[1] = CreateEventA(NULL, FALSE, FALSE, "Wine COM Test Repeat Event"); +again: hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&TestOOP_ClassFactory, CLSCTX_LOCAL_SERVER, REGCLS_SINGLEUSE, &cookie); ok_ole_success(hr, CoRegisterClassObject); - ready_event = CreateEventA(NULL, FALSE, FALSE, "Wine COM Test Ready Event"); SetEvent(ready_event); - quit_event = CreateEventA(NULL, FALSE, FALSE, "Wine COM Test Quit Event"); - do { - wait = MsgWaitForMultipleObjects(1, &quit_event, FALSE, 30000, QS_ALLINPUT); - if (wait == WAIT_OBJECT_0+1) + wait = MsgWaitForMultipleObjects(2, handles, FALSE, 30000, QS_ALLINPUT); + if (wait == WAIT_OBJECT_0+2) { MSG msg; @@ -3024,12 +3082,20 @@ static void test_register_local_server(void) DispatchMessageA(&msg); } } + else if (wait == WAIT_OBJECT_0+1) + { + hr = CoRevokeClassObject(cookie); + ok_ole_success(hr, CoRevokeClassObject); + goto again; + } } - while (wait == WAIT_OBJECT_0+1); + while (wait == WAIT_OBJECT_0+2); ok( wait == WAIT_OBJECT_0, "quit event wait timed out\n" ); hr = CoRevokeClassObject(cookie); ok_ole_success(hr, CoRevokeClassObject); + CloseHandle(handles[0]); + CloseHandle(handles[1]); } static HANDLE create_target_process(const char *arg) @@ -3057,10 +3123,13 @@ static void test_local_server(void) DWORD cookie; HRESULT hr; IClassFactory * cf; + IPersist *persist; DWORD ret; HANDLE process; HANDLE quit_event; HANDLE ready_event; + HANDLE repeat_event; + CLSID clsid; heventShutdown = CreateEventA(NULL, TRUE, FALSE, NULL); @@ -3127,16 +3196,30 @@ static void test_local_server(void) ready_event = CreateEventA(NULL, FALSE, FALSE, "Wine COM Test Ready Event"); ok( !WaitForSingleObject(ready_event, 10000), "wait timed out\n" ); - CloseHandle(ready_event); - hr = CoCreateInstance(&CLSID_WineOOPTest, NULL, CLSCTX_LOCAL_SERVER, &IID_IClassFactory, (void **)&cf); + hr = CoCreateInstance(&CLSID_WineOOPTest, NULL, CLSCTX_LOCAL_SERVER, &IID_IPersist, (void **)&persist); ok_ole_success(hr, CoCreateInstance); - IClassFactory_Release(cf); + IPersist_Release(persist); - hr = CoCreateInstance(&CLSID_WineOOPTest, NULL, CLSCTX_LOCAL_SERVER, &IID_IClassFactory, (void **)&cf); + hr = CoCreateInstance(&CLSID_WineOOPTest, NULL, CLSCTX_LOCAL_SERVER, &IID_IPersist, (void **)&persist); ok(hr == REGDB_E_CLASSNOTREG, "Second CoCreateInstance on REGCLS_SINGLEUSE object should have failed\n"); + /* Re-register the class and try calling CoDisconnectObject from within a call to that object */ + repeat_event = CreateEventA(NULL, FALSE, FALSE, "Wine COM Test Repeat Event"); + SetEvent(repeat_event); + CloseHandle(repeat_event); + + ok( !WaitForSingleObject(ready_event, 10000), "wait timed out\n" ); + CloseHandle(ready_event); + + hr = CoCreateInstance(&CLSID_WineOOPTest, NULL, CLSCTX_LOCAL_SERVER, &IID_IPersist, (void **)&persist); + ok_ole_success(hr, CoCreateInstance); + + /* GetClassID will call CoDisconnectObject */ + IPersist_GetClassID(persist, &clsid); + IPersist_Release(persist); + quit_event = CreateEventA(NULL, FALSE, FALSE, "Wine COM Test Quit Event"); SetEvent(quit_event);