Rob Shearman : ole32: Don' t keep the local server named pipe open for a single-use object.

Alexandre Julliard julliard at wine.codeweavers.com
Fri Mar 9 15:47:46 CST 2007


Module: wine
Branch: master
Commit: 15a0b7fad5eb3239cd058dde490918422db481a5
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=15a0b7fad5eb3239cd058dde490918422db481a5

Author: Rob Shearman <rob at codeweavers.com>
Date:   Fri Mar  9 17:51:36 2007 +0000

ole32: Don't keep the local server named pipe open for a single-use object.

---

 dlls/ole32/compobj.c         |    1 +
 dlls/ole32/compobj_private.h |    2 +-
 dlls/ole32/rpc.c             |   12 ++++-
 dlls/ole32/tests/marshal.c   |  114 +++++++++++++++++++++++++++++++++++++++--
 4 files changed, 121 insertions(+), 8 deletions(-)

diff --git a/dlls/ole32/compobj.c b/dlls/ole32/compobj.c
index 98ec995..900fc68 100644
--- a/dlls/ole32/compobj.c
+++ b/dlls/ole32/compobj.c
@@ -1622,6 +1622,7 @@ HRESULT WINAPI CoRegisterClassObject(
 
       hr = RPC_StartLocalServer(&newClass->classIdentifier,
                                 newClass->pMarshaledData,
+                                flags & (REGCLS_MULTIPLEUSE|REGCLS_MULTI_SEPARATE),
                                 &newClass->RpcRegistration);
   }
   return S_OK;
diff --git a/dlls/ole32/compobj_private.h b/dlls/ole32/compobj_private.h
index 4c96a3c..a85a72d 100644
--- a/dlls/ole32/compobj_private.h
+++ b/dlls/ole32/compobj_private.h
@@ -221,7 +221,7 @@ HRESULT RPC_CreateServerChannel(IRpcChannelBuffer **chan);
 void    RPC_ExecuteCall(struct dispatch_params *params);
 HRESULT RPC_RegisterInterface(REFIID riid);
 void    RPC_UnregisterInterface(REFIID riid);
-HRESULT RPC_StartLocalServer(REFCLSID clsid, IStream *stream, void **registration);
+HRESULT RPC_StartLocalServer(REFCLSID clsid, IStream *stream, BOOL multi_use, void **registration);
 void    RPC_StopLocalServer(void *registration);
 HRESULT RPC_GetLocalClassObject(REFCLSID rclsid, REFIID iid, LPVOID *ppv);
 HRESULT RPC_RegisterChannelHook(REFGUID rguid, IChannelHook *hook);
diff --git a/dlls/ole32/rpc.c b/dlls/ole32/rpc.c
index 3320552..d6b1a66 100644
--- a/dlls/ole32/rpc.c
+++ b/dlls/ole32/rpc.c
@@ -1732,6 +1732,7 @@ struct local_server_params
     CLSID clsid;
     IStream *stream;
     HANDLE ready_event;
+    BOOL multi_use;
     HANDLE pipe;
 };
 
@@ -1749,6 +1750,7 @@ static DWORD WINAPI local_server_thread(LPVOID param)
     LARGE_INTEGER	seekto;
     ULARGE_INTEGER	newpos;
     ULONG		res;
+    BOOL multi_use = lsp->multi_use;
 
     TRACE("Starting threader for %s.\n",debugstr_guid(&lsp->clsid));
 
@@ -1817,13 +1819,20 @@ static DWORD WINAPI local_server_thread(LPVOID param)
         DisconnectNamedPipe(hPipe);
 
         TRACE("done marshalling IClassFactory\n");
+
+        if (!multi_use)
+        {
+            TRACE("single use object, shutting down pipe %s\n", debugstr_w(pipefn));
+            CloseHandle(hPipe);
+            break;
+        }
     }
     IStream_Release(pStm);
     return 0;
 }
 
 /* starts listening for a local server */
-HRESULT RPC_StartLocalServer(REFCLSID clsid, IStream *stream, void **registration)
+HRESULT RPC_StartLocalServer(REFCLSID clsid, IStream *stream, BOOL multi_use, void **registration)
 {
     DWORD tid;
     HANDLE thread, ready_event;
@@ -1833,6 +1842,7 @@ HRESULT RPC_StartLocalServer(REFCLSID clsid, IStream *stream, void **registratio
     lsp->stream = stream;
     IStream_AddRef(stream);
     lsp->ready_event = ready_event = CreateEventW(NULL, FALSE, FALSE, NULL);
+    lsp->multi_use = multi_use;
 
     thread = CreateThread(NULL, 0, local_server_thread, lsp, 0, &tid);
     if (!thread)
diff --git a/dlls/ole32/tests/marshal.c b/dlls/ole32/tests/marshal.c
index f06475d..12ab39b 100644
--- a/dlls/ole32/tests/marshal.c
+++ b/dlls/ole32/tests/marshal.c
@@ -23,6 +23,7 @@
 #define CONST_VTABLE
 
 #include <stdarg.h>
+#include <stdio.h>
 
 #include "windef.h"
 #include "winbase.h"
@@ -50,6 +51,14 @@ static const IID IID_IWineTest =
 #define EXTENTID_WineTest IID_IWineTest
 #define CLSID_WineTest IID_IWineTest
 
+static const CLSID CLSID_WineOOPTest =
+{
+    0x5201163f,
+    0x8164,
+    0x4fd0,
+    {0xa1, 0xa2, 0x5d, 0x5a, 0x36, 0x54, 0xd3, 0xbd}
+}; /* 5201163f-8164-4fd0-a1a2-5d5a3654d3bd */
+
 static void test_cocreateinstance_proxy(void)
 {
     IUnknown *pProxy;
@@ -2152,6 +2161,11 @@ 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;
 }
 
@@ -2177,19 +2191,72 @@ static const IClassFactoryVtbl TestClassFactoryOOP_Vtbl =
 
 static IClassFactory TestOOP_ClassFactory = { &TestClassFactoryOOP_Vtbl };
 
+static void test_register_local_server(void)
+{
+    DWORD cookie;
+    HRESULT hr;
+    HANDLE ready_event;
+    HANDLE quit_event;
+    DWORD wait;
+
+    heventShutdown = CreateEvent(NULL, TRUE, FALSE, NULL);
+
+    hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&TestOOP_ClassFactory,
+                               CLSCTX_LOCAL_SERVER, REGCLS_SINGLEUSE, &cookie);
+    ok_ole_success(hr, CoRegisterClassObject);
+
+    ready_event = CreateEvent(NULL, FALSE, FALSE, "Wine COM Test Ready Event");
+    SetEvent(ready_event);
+
+    quit_event = CreateEvent(NULL, FALSE, FALSE, "Wine COM Test Quit Event");
+
+    do
+    {
+        wait = MsgWaitForMultipleObjects(1, &quit_event, FALSE, INFINITE, QS_ALLINPUT);
+        if (wait == WAIT_OBJECT_0+1)
+        {
+            MSG msg;
+            BOOL ret = PeekMessage(&msg, NULL, 0, 0, PM_REMOVE);
+            if (ret)
+            {
+                trace("Message 0x%x\n", msg.message);
+                TranslateMessage(&msg);
+                DispatchMessage(&msg);
+            }
+        }
+    }
+    while (wait == WAIT_OBJECT_0+1);
+
+    hr = CoRevokeClassObject(cookie);
+    ok_ole_success(hr, CoRevokeClassObject);
+}
+
+static HANDLE create_target_process(const char *arg)
+{
+    char **argv;
+    char cmdline[MAX_PATH];
+    PROCESS_INFORMATION pi;
+    STARTUPINFO si = { 0 };
+    si.cb = sizeof(si);
+
+    winetest_get_mainargs( &argv );
+    sprintf(cmdline, "%s %s %s", argv[0], argv[1], arg);
+    ok(CreateProcess(argv[0], cmdline, NULL, NULL, FALSE, 0, NULL, NULL,
+                     &si, &pi) != 0, "error: %u\n", GetLastError());
+    ok(CloseHandle(pi.hThread) != 0, "error %u\n", GetLastError());
+    return pi.hProcess;
+}
+
 /* tests functions commonly used by out of process COM servers */
 static void test_local_server(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 * cf;
     DWORD ret;
+    HANDLE process;
+    HANDLE quit_event;
+    HANDLE ready_event;
 
     heventShutdown = CreateEvent(NULL, TRUE, FALSE, NULL);
 
@@ -2249,6 +2316,28 @@ static void test_local_server(void)
     ok_ole_success(hr, CoRevokeClassObject);
 
     CloseHandle(heventShutdown);
+
+    process = create_target_process("-Embedding");
+    ok(process != NULL, "couldn't start local server process, error was %d\n", GetLastError());
+
+    ready_event = CreateEvent(NULL, FALSE, FALSE, "Wine COM Test Ready Event");
+    WaitForSingleObject(ready_event, 1000);
+    CloseHandle(ready_event);
+
+    hr = CoCreateInstance(&CLSID_WineOOPTest, NULL, CLSCTX_LOCAL_SERVER, &IID_IClassFactory, (void **)&cf);
+    ok_ole_success(hr, CoCreateInstance);
+
+    IClassFactory_Release(cf);
+
+    hr = CoCreateInstance(&CLSID_WineOOPTest, NULL, CLSCTX_LOCAL_SERVER, &IID_IClassFactory, (void **)&cf);
+    ok(hr == REGDB_E_CLASSNOTREG, "Second CoCreateInstance on REGCLS_SINGLEUSE object should have failed\n");
+
+    quit_event = CreateEvent(NULL, FALSE, FALSE, "Wine COM Test Quit Event");
+    SetEvent(quit_event);
+
+    WaitForSingleObject(process, INFINITE);
+    CloseHandle(quit_event);
+    CloseHandle(process);
 }
 
 struct git_params
@@ -2532,8 +2621,21 @@ START_TEST(marshal)
 {
     WNDCLASS wndclass;
     HMODULE hOle32 = GetModuleHandle("ole32");
+    int argc;
+    char **argv;
+
     if (!(pCoInitializeEx = (void*)GetProcAddress(hOle32, "CoInitializeEx"))) goto no_test;
 
+    argc = winetest_get_mainargs( &argv );
+    if (argc > 2 && (!strcmp(argv[2], "-Embedding")))
+    {
+        pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
+        test_register_local_server();
+        CoUninitialize();
+
+        return;
+    }
+
     /* register a window class used in several tests */
     memset(&wndclass, 0, sizeof(wndclass));
     wndclass.lpfnWndProc = window_proc;




More information about the wine-cvs mailing list