[PATCH 3/4] ole32/tests: Test calling CoDisconnectObject from within a COM call to the object.

Huw Davies huw at codeweavers.com
Tue Oct 13 08:49:16 CDT 2015


Signed-off-by: Huw Davies <huw at codeweavers.com>
---
 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);
 
-- 
1.8.0




More information about the wine-patches mailing list