Module: wine Branch: master Commit: 1dcf3f8e0a7969ffcc99b025aa1ec30837e0adba URL: http://source.winehq.org/git/wine.git/?a=commit;h=1dcf3f8e0a7969ffcc99b025aa...
Author: Huw Davies huw@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@codeweavers.com Signed-off-by: Alexandre Julliard julliard@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);