[PATCH 2/4] combase: Move server class registration.

Nikolay Sivov nsivov at codeweavers.com
Fri Aug 28 03:05:18 CDT 2020


Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
---
 dlls/combase/apartment.c       |  10 +-
 dlls/combase/combase.c         | 274 ++++++++++++++++++++++++-
 dlls/combase/combase.spec      |   9 +-
 dlls/combase/combase_private.h |   9 +-
 dlls/combase/rpc.c             | 170 ++++++++++++++++
 dlls/ole32/compobj.c           | 361 ---------------------------------
 dlls/ole32/compobj_private.h   |   8 -
 dlls/ole32/ole32.spec          |  10 +-
 dlls/ole32/rpc.c               | 179 ----------------
 9 files changed, 457 insertions(+), 573 deletions(-)

diff --git a/dlls/combase/apartment.c b/dlls/combase/apartment.c
index 3df8b165c13..356935ae26b 100644
--- a/dlls/combase/apartment.c
+++ b/dlls/combase/apartment.c
@@ -285,9 +285,6 @@ static ULONG WINAPI local_server_Release(IServiceProvider *iface)
     return refcount;
 }
 
-extern HRESULT WINAPI InternalGetRegisteredClassObject(struct apartment *apt, REFGUID guid,
-        DWORD clscontext, IUnknown **obj);
-
 static HRESULT WINAPI local_server_QueryService(IServiceProvider *iface, REFGUID guid, REFIID riid, void **obj)
 {
     struct local_server *local_server = impl_from_IServiceProvider(iface);
@@ -300,7 +297,7 @@ static HRESULT WINAPI local_server_QueryService(IServiceProvider *iface, REFGUID
     if (!local_server->apt)
         return E_UNEXPECTED;
 
-    if (SUCCEEDED(InternalGetRegisteredClassObject(apt, guid, CLSCTX_LOCAL_SERVER, &unk)))
+    if ((unk = com_get_registered_class_object(apt, guid, CLSCTX_LOCAL_SERVER)))
     {
         hr = IUnknown_QueryInterface(unk, riid, obj);
         IUnknown_Release(unk);
@@ -317,7 +314,7 @@ static const IServiceProviderVtbl local_server_vtbl =
     local_server_QueryService
 };
 
-HRESULT WINAPI apartment_get_local_server_stream(struct apartment *apt, IStream **ret)
+HRESULT apartment_get_local_server_stream(struct apartment *apt, IStream **ret)
 {
     HRESULT hr = S_OK;
 
@@ -446,7 +443,6 @@ void apartment_freeunusedlibraries(struct apartment *apt, DWORD delay)
     LeaveCriticalSection(&apt->cs);
 }
 
-extern void WINAPI InternalRevokeAllClasses(struct apartment *apt);
 extern HRESULT WINAPI Internal_apartment_disconnectproxies(struct apartment *apt);
 extern ULONG WINAPI Internal_stub_manager_int_release(struct stub_manager *stubmgr);
 
@@ -499,7 +495,7 @@ void WINAPI apartment_release(struct apartment *apt)
         }
 
         /* Release the references to the registered class objects */
-        InternalRevokeAllClasses(apt);
+        apartment_revoke_all_classes(apt);
 
         /* no locking is needed for this apartment, because no other thread
          * can access it at this point */
diff --git a/dlls/combase/combase.c b/dlls/combase/combase.c
index 28a63c6c7f4..6d058ea6fa5 100644
--- a/dlls/combase/combase.c
+++ b/dlls/combase/combase.c
@@ -47,6 +47,8 @@ extern HRESULT WINAPI Ole32DllGetClassObject(REFCLSID rclsid, REFIID riid, void
  */
 static LONG com_lockcount;
 
+static LONG com_server_process_refcount;
+
 struct comclassredirect_data
 {
     ULONG size;
@@ -113,6 +115,57 @@ static CRITICAL_SECTION_DEBUG psclsid_cs_debug =
 };
 static CRITICAL_SECTION cs_registered_ps = { &psclsid_cs_debug, -1, 0, 0, 0, 0 };
 
+/*
+ * TODO: Make this data structure aware of inter-process communication. This
+ *       means that parts of this will be exported to rpcss.
+ */
+struct registered_class
+{
+    struct list entry;
+    CLSID clsid;
+    OXID apartment_id;
+    IUnknown *object;
+    DWORD clscontext;
+    DWORD flags;
+    DWORD cookie;
+    void *RpcRegistration;
+};
+
+static struct list registered_classes = LIST_INIT(registered_classes);
+
+static CRITICAL_SECTION registered_classes_cs;
+static CRITICAL_SECTION_DEBUG registered_classes_cs_debug =
+{
+    0, 0, &registered_classes_cs,
+    { &registered_classes_cs_debug.ProcessLocksList, &registered_classes_cs_debug.ProcessLocksList },
+      0, 0, { (DWORD_PTR)(__FILE__ ": registered_classes_cs") }
+};
+static CRITICAL_SECTION registered_classes_cs = { &registered_classes_cs_debug, -1, 0, 0, 0, 0 };
+
+IUnknown * com_get_registered_class_object(const struct apartment *apt, REFCLSID rclsid, DWORD clscontext)
+{
+    struct registered_class *cur;
+    IUnknown *object = NULL;
+
+    EnterCriticalSection(&registered_classes_cs);
+
+    LIST_FOR_EACH_ENTRY(cur, &registered_classes, struct registered_class, entry)
+    {
+        if ((apt->oxid == cur->apartment_id) &&
+            (clscontext & cur->clscontext) &&
+            IsEqualGUID(&cur->clsid, rclsid))
+        {
+            object = cur->object;
+            IUnknown_AddRef(cur->object);
+            break;
+        }
+    }
+
+    LeaveCriticalSection(&registered_classes_cs);
+
+    return object;
+}
+
 static struct init_spy *get_spy_entry(struct tlsdata *tlsdata, unsigned int id)
 {
     struct init_spy *spy;
@@ -1498,8 +1551,8 @@ HRESULT WINAPI DECLSPEC_HOTPATCH CoGetClassObject(REFCLSID rclsid, DWORD clscont
         COSERVERINFO *server_info, REFIID riid, void **obj)
 {
     struct class_reg_data clsreg = { 0 };
-    IUnknown *regClassObject;
     HRESULT hr = E_UNEXPECTED;
+    IUnknown *registered_obj;
     struct apartment *apt;
 
     TRACE("%s, %s\n", debugstr_guid(rclsid), debugstr_guid(riid));
@@ -1558,10 +1611,10 @@ HRESULT WINAPI DECLSPEC_HOTPATCH CoGetClassObject(REFCLSID rclsid, DWORD clscont
      * First, try and see if we can't match the class ID with one of the
      * registered classes.
      */
-    if (InternalGetRegisteredClassObject(apt, rclsid, clscontext, &regClassObject) == S_OK)
+    if ((registered_obj = com_get_registered_class_object(apt, rclsid, clscontext)))
     {
-        hr = IUnknown_QueryInterface(regClassObject, riid, obj);
-        IUnknown_Release(regClassObject);
+        hr = IUnknown_QueryInterface(registered_obj, riid, obj);
+        IUnknown_Release(registered_obj);
         apartment_release(apt);
         return hr;
     }
@@ -2676,6 +2729,215 @@ HRESULT WINAPI CoGetApartmentType(APTTYPE *type, APTTYPEQUALIFIER *qualifier)
     return tlsdata->apt ? S_OK : CO_E_NOTINITIALIZED;
 }
 
+/******************************************************************************
+ *        CoRegisterClassObject    (combase.@)
+ * BUGS
+ *  MSDN claims that multiple interface registrations are legal, but we
+ *  can't do that with our current implementation.
+ */
+HRESULT WINAPI CoRegisterClassObject(REFCLSID rclsid, IUnknown *object, DWORD clscontext,
+        DWORD flags, DWORD *cookie)
+{
+    static LONG next_cookie;
+
+    struct registered_class *newclass;
+    IUnknown *found_object;
+    struct apartment *apt;
+    HRESULT hr = S_OK;
+
+    TRACE("%s, %p, %#x, %#x, %p\n", debugstr_guid(rclsid), object, clscontext, flags, cookie);
+
+    if (!cookie || !object)
+        return E_INVALIDARG;
+
+    if (!(apt = apartment_get_current_or_mta()))
+    {
+        ERR("COM was not initialized\n");
+        return CO_E_NOTINITIALIZED;
+    }
+
+    *cookie = 0;
+
+    /* REGCLS_MULTIPLEUSE implies registering as inproc server. This is what
+     * differentiates the flag from REGCLS_MULTI_SEPARATE. */
+    if (flags & REGCLS_MULTIPLEUSE)
+        clscontext |= CLSCTX_INPROC_SERVER;
+
+    /*
+     * First, check if the class is already registered.
+     * If it is, this should cause an error.
+     */
+    if ((found_object = com_get_registered_class_object(apt, rclsid, clscontext)))
+    {
+        if (flags & REGCLS_MULTIPLEUSE)
+        {
+            if (clscontext & CLSCTX_LOCAL_SERVER)
+                hr = CoLockObjectExternal(found_object, TRUE, FALSE);
+            IUnknown_Release(found_object);
+            apartment_release(apt);
+            return hr;
+        }
+
+        IUnknown_Release(found_object);
+        ERR("object already registered for class %s\n", debugstr_guid(rclsid));
+        apartment_release(apt);
+        return CO_E_OBJISREG;
+    }
+
+    newclass = heap_alloc(sizeof(*newclass));
+    if (!newclass)
+    {
+        apartment_release(apt);
+        return E_OUTOFMEMORY;
+    }
+
+    newclass->clsid = *rclsid;
+    newclass->apartment_id = apt->oxid;
+    newclass->clscontext = clscontext;
+    newclass->flags = flags;
+    newclass->RpcRegistration = NULL;
+
+    if (!(newclass->cookie = InterlockedIncrement(&next_cookie)))
+        newclass->cookie = InterlockedIncrement(&next_cookie);
+
+    newclass->object = object;
+    IUnknown_AddRef(newclass->object);
+
+    EnterCriticalSection(&registered_classes_cs);
+    list_add_tail(&registered_classes, &newclass->entry);
+    LeaveCriticalSection(&registered_classes_cs);
+
+    *cookie = newclass->cookie;
+
+    if (clscontext & CLSCTX_LOCAL_SERVER)
+    {
+        IStream *marshal_stream;
+
+        hr = apartment_get_local_server_stream(apt, &marshal_stream);
+        if(FAILED(hr))
+        {
+            apartment_release(apt);
+            return hr;
+        }
+
+        hr = rpc_start_local_server(&newclass->clsid, marshal_stream, flags & (REGCLS_MULTIPLEUSE|REGCLS_MULTI_SEPARATE),
+                &newclass->RpcRegistration);
+        IStream_Release(marshal_stream);
+    }
+
+    apartment_release(apt);
+    return S_OK;
+}
+
+static void com_revoke_class_object(struct registered_class *entry)
+{
+    list_remove(&entry->entry);
+
+    if (entry->clscontext & CLSCTX_LOCAL_SERVER)
+        rpc_stop_local_server(entry->RpcRegistration);
+
+    IUnknown_Release(entry->object);
+    heap_free(entry);
+}
+
+void apartment_revoke_all_classes(const struct apartment *apt)
+{
+    struct registered_class *cur, *cur2;
+
+    EnterCriticalSection(&registered_classes_cs);
+
+    LIST_FOR_EACH_ENTRY_SAFE(cur, cur2, &registered_classes, struct registered_class, entry)
+    {
+        if (cur->apartment_id == apt->oxid)
+            com_revoke_class_object(cur);
+    }
+
+    LeaveCriticalSection(&registered_classes_cs);
+}
+
+/***********************************************************************
+ *           CoRevokeClassObject    (combase.@)
+ */
+HRESULT WINAPI DECLSPEC_HOTPATCH CoRevokeClassObject(DWORD cookie)
+{
+    HRESULT hr = E_INVALIDARG;
+    struct registered_class *cur;
+    struct apartment *apt;
+
+    TRACE("%#x\n", cookie);
+
+    if (!(apt = apartment_get_current_or_mta()))
+    {
+        ERR("COM was not initialized\n");
+        return CO_E_NOTINITIALIZED;
+    }
+
+    EnterCriticalSection(&registered_classes_cs);
+
+    LIST_FOR_EACH_ENTRY(cur, &registered_classes, struct registered_class, entry)
+    {
+        if (cur->cookie != cookie)
+            continue;
+
+        if (cur->apartment_id == apt->oxid)
+        {
+            com_revoke_class_object(cur);
+            hr = S_OK;
+        }
+        else
+        {
+            ERR("called from wrong apartment, should be called from %s\n", wine_dbgstr_longlong(cur->apartment_id));
+            hr = RPC_E_WRONG_THREAD;
+        }
+
+        break;
+    }
+
+    LeaveCriticalSection(&registered_classes_cs);
+    apartment_release(apt);
+
+    return hr;
+}
+
+/***********************************************************************
+ *           CoAddRefServerProcess    (combase.@)
+ */
+ULONG WINAPI CoAddRefServerProcess(void)
+{
+    ULONG refs;
+
+    TRACE("\n");
+
+    EnterCriticalSection(&registered_classes_cs);
+    refs = ++com_server_process_refcount;
+    LeaveCriticalSection(&registered_classes_cs);
+
+    TRACE("refs before: %d\n", refs - 1);
+
+    return refs;
+}
+
+/***********************************************************************
+ *           CoReleaseServerProcess [OLE32.@]
+ */
+ULONG WINAPI CoReleaseServerProcess(void)
+{
+    ULONG refs;
+
+    TRACE("\n");
+
+    EnterCriticalSection(&registered_classes_cs);
+
+    refs = --com_server_process_refcount;
+    /* FIXME: suspend objects */
+
+    LeaveCriticalSection(&registered_classes_cs);
+
+    TRACE("refs after: %d\n", refs);
+
+    return refs;
+}
+
 /***********************************************************************
  *            DllMain     (combase.@)
  */
@@ -2688,6 +2950,10 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD reason, LPVOID reserved)
     case DLL_PROCESS_ATTACH:
         hProxyDll = hinstDLL;
         break;
+    case DLL_PROCESS_DETACH:
+        if (reserved) break;
+        DeleteCriticalSection(&registered_classes_cs);
+        break;
     }
 
     return TRUE;
diff --git a/dlls/combase/combase.spec b/dlls/combase/combase.spec
index ea2177ca7ba..401979119b4 100644
--- a/dlls/combase/combase.spec
+++ b/dlls/combase/combase.spec
@@ -73,7 +73,7 @@
 @ stub CleanupOleStateInAllTls
 @ stdcall CleanupTlsOleState(ptr)
 @ stub ClearCleanupFlag
-@ stdcall CoAddRefServerProcess() ole32.CoAddRefServerProcess
+@ stdcall CoAddRefServerProcess()
 @ stub CoAllowUnmarshalerCLSID
 @ stub CoCancelCall
 @ stdcall CoCopyProxy(ptr ptr)
@@ -139,7 +139,7 @@
 @ stdcall CoQueryProxyBlanket(ptr ptr ptr ptr ptr ptr ptr ptr)
 @ stub CoReactivateObject
 @ stub CoRegisterActivationFilter
-@ stdcall CoRegisterClassObject(ptr ptr long long ptr) ole32.CoRegisterClassObject
+@ stdcall CoRegisterClassObject(ptr ptr long long ptr)
 @ stdcall CoRegisterInitializeSpy(ptr ptr)
 @ stdcall CoRegisterMallocSpy(ptr)
 @ stdcall CoRegisterMessageFilter(ptr ptr)
@@ -147,11 +147,11 @@
 @ stdcall CoRegisterSurrogate(ptr) ole32.CoRegisterSurrogate
 @ stdcall CoRegisterSurrogateEx(ptr ptr) ole32.CoRegisterSurrogateEx
 @ stdcall CoReleaseMarshalData(ptr) ole32.CoReleaseMarshalData
-@ stdcall CoReleaseServerProcess() ole32.CoReleaseServerProcess
+@ stdcall CoReleaseServerProcess()
 @ stdcall CoResumeClassObjects() ole32.CoResumeClassObjects
 @ stub CoRetireServer
 @ stdcall CoRevertToSelf()
-@ stdcall CoRevokeClassObject(long) ole32.CoRevokeClassObject
+@ stdcall CoRevokeClassObject(long)
 @ stdcall CoRevokeInitializeSpy(int64)
 @ stdcall CoRevokeMallocSpy()
 @ stub CoSetCancelObject
@@ -359,5 +359,4 @@
 @ stdcall apartment_getwindow(ptr)
 @ stdcall apartment_global_cleanup()
 @ stdcall apartment_createwindowifneeded(ptr)
-@ stdcall apartment_get_local_server_stream(ptr ptr)
 @ stdcall apartment_findfromtid(long)
diff --git a/dlls/combase/combase_private.h b/dlls/combase/combase_private.h
index c6d090707a7..61b76657494 100644
--- a/dlls/combase/combase_private.h
+++ b/dlls/combase/combase_private.h
@@ -54,9 +54,6 @@ struct apartment
     struct list usage_cookies; /* Used for refcount control with CoIncrementMTAUsage()/CoDecrementMTAUsage(). */
 };
 
-extern HRESULT WINAPI InternalGetRegisteredClassObject(struct apartment *apt, REFGUID guid,
-        DWORD clscontext, IUnknown **obj);
-
 HRESULT open_key_for_clsid(REFCLSID clsid, const WCHAR *keyname, REGSAM access, HKEY *subkey) DECLSPEC_HIDDEN;
 HRESULT open_appidkey_from_clsid(REFCLSID clsid, REGSAM access, HKEY *subkey) DECLSPEC_HIDDEN;
 
@@ -112,6 +109,8 @@ void apartment_freeunusedlibraries(struct apartment *apt, DWORD unload_delay) DE
 /* RpcSs interface */
 HRESULT rpcss_get_next_seqid(DWORD *id) DECLSPEC_HIDDEN;
 HRESULT rpc_get_local_class_object(REFCLSID rclsid, REFIID riid, void **obj) DECLSPEC_HIDDEN;
+HRESULT rpc_start_local_server(REFCLSID clsid, IStream *stream, BOOL multi_use, void **registration) DECLSPEC_HIDDEN;
+void rpc_stop_local_server(void *registration) DECLSPEC_HIDDEN;
 
 /* stub managers hold refs on the object and each interface stub */
 struct stub_manager
@@ -171,6 +170,10 @@ void apartment_decrement_mta_usage(CO_MTA_USAGE_COOKIE cookie) DECLSPEC_HIDDEN;
 struct apartment * apartment_get_mta(void) DECLSPEC_HIDDEN;
 HRESULT apartment_get_inproc_class_object(struct apartment *apt, const struct class_reg_data *regdata,
         REFCLSID rclsid, REFIID riid, BOOL hostifnecessary, void **ppv) DECLSPEC_HIDDEN;
+HRESULT apartment_get_local_server_stream(struct apartment *apt, IStream **ret) DECLSPEC_HIDDEN;
+IUnknown *com_get_registered_class_object(const struct apartment *apartment, REFCLSID rclsid,
+        DWORD clscontext) DECLSPEC_HIDDEN;
+void apartment_revoke_all_classes(const struct apartment *apt) DECLSPEC_HIDDEN;
 
 /* Stub Manager */
 
diff --git a/dlls/combase/rpc.c b/dlls/combase/rpc.c
index 2b655da8bad..cb503e9ae7c 100644
--- a/dlls/combase/rpc.c
+++ b/dlls/combase/rpc.c
@@ -459,3 +459,173 @@ out:
     IStream_Release(pStm);
     return hr;
 }
+
+struct local_server_params
+{
+    CLSID clsid;
+    IStream *stream;
+    HANDLE pipe;
+    HANDLE stop_event;
+    HANDLE thread;
+    BOOL multi_use;
+};
+
+/* FIXME: should call to rpcss instead */
+static DWORD WINAPI local_server_thread(void *param)
+{
+    struct local_server_params * lsp = param;
+    WCHAR 		pipefn[100];
+    HRESULT		hres;
+    IStream		*pStm = lsp->stream;
+    STATSTG		ststg;
+    unsigned char	*buffer;
+    int 		buflen;
+    LARGE_INTEGER	seekto;
+    ULARGE_INTEGER	newpos;
+    ULONG		res;
+    BOOL multi_use = lsp->multi_use;
+    OVERLAPPED ovl;
+    HANDLE pipe_event, hPipe = lsp->pipe, new_pipe;
+    DWORD  bytes;
+
+    TRACE("Starting threader for %s.\n",debugstr_guid(&lsp->clsid));
+
+    memset(&ovl, 0, sizeof(ovl));
+    get_localserver_pipe_name(pipefn, &lsp->clsid);
+    ovl.hEvent = pipe_event = CreateEventW(NULL, FALSE, FALSE, NULL);
+
+    while (1) {
+        if (!ConnectNamedPipe(hPipe, &ovl))
+        {
+            DWORD error = GetLastError();
+            if (error == ERROR_IO_PENDING)
+            {
+                HANDLE handles[2] = { pipe_event, lsp->stop_event };
+                DWORD ret;
+                ret = WaitForMultipleObjects(2, handles, FALSE, INFINITE);
+                if (ret != WAIT_OBJECT_0)
+                    break;
+            }
+            /* client already connected isn't an error */
+            else if (error != ERROR_PIPE_CONNECTED)
+            {
+                ERR("ConnectNamedPipe failed with error %d\n", GetLastError());
+                break;
+            }
+        }
+
+        TRACE("marshalling LocalServer to client\n");
+
+        hres = IStream_Stat(pStm,&ststg,STATFLAG_NONAME);
+        if (hres != S_OK)
+            break;
+
+        seekto.u.LowPart = 0;
+        seekto.u.HighPart = 0;
+        hres = IStream_Seek(pStm,seekto,STREAM_SEEK_SET,&newpos);
+        if (hres != S_OK) {
+            FIXME("IStream_Seek failed, %x\n",hres);
+            break;
+        }
+
+        buflen = ststg.cbSize.u.LowPart;
+        buffer = HeapAlloc(GetProcessHeap(),0,buflen);
+
+        hres = IStream_Read(pStm,buffer,buflen,&res);
+        if (hres != S_OK) {
+            FIXME("Stream Read failed, %x\n",hres);
+            HeapFree(GetProcessHeap(),0,buffer);
+            break;
+        }
+
+        WriteFile(hPipe,buffer,buflen,&res,&ovl);
+        GetOverlappedResult(hPipe, &ovl, &bytes, TRUE);
+        HeapFree(GetProcessHeap(),0,buffer);
+
+        FlushFileBuffers(hPipe);
+        DisconnectNamedPipe(hPipe);
+        TRACE("done marshalling LocalServer\n");
+
+        if (!multi_use)
+        {
+            TRACE("single use object, shutting down pipe %s\n", debugstr_w(pipefn));
+            break;
+        }
+        new_pipe = CreateNamedPipeW( pipefn, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
+                                     PIPE_TYPE_BYTE|PIPE_WAIT, PIPE_UNLIMITED_INSTANCES,
+                                     4096, 4096, 500 /* 0.5 second timeout */, NULL );
+        if (new_pipe == INVALID_HANDLE_VALUE)
+        {
+            FIXME("pipe creation failed for %s, le is %u\n", debugstr_w(pipefn), GetLastError());
+            break;
+        }
+        CloseHandle(hPipe);
+        hPipe = new_pipe;
+    }
+
+    CloseHandle(pipe_event);
+    CloseHandle(hPipe);
+    return 0;
+}
+
+HRESULT rpc_start_local_server(REFCLSID clsid, IStream *stream, BOOL multi_use, void **registration)
+{
+    DWORD tid, err;
+    struct local_server_params *lsp;
+    WCHAR pipefn[100];
+
+    lsp = HeapAlloc(GetProcessHeap(), 0, sizeof(*lsp));
+    if (!lsp)
+        return E_OUTOFMEMORY;
+
+    lsp->clsid = *clsid;
+    lsp->stream = stream;
+    IStream_AddRef(stream);
+    lsp->stop_event = CreateEventW(NULL, FALSE, FALSE, NULL);
+    if (!lsp->stop_event)
+    {
+        HeapFree(GetProcessHeap(), 0, lsp);
+        return HRESULT_FROM_WIN32(GetLastError());
+    }
+    lsp->multi_use = multi_use;
+
+    get_localserver_pipe_name(pipefn, &lsp->clsid);
+    lsp->pipe = CreateNamedPipeW(pipefn, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
+                                 PIPE_TYPE_BYTE|PIPE_WAIT, PIPE_UNLIMITED_INSTANCES,
+                                 4096, 4096, 500 /* 0.5 second timeout */, NULL);
+    if (lsp->pipe == INVALID_HANDLE_VALUE)
+    {
+        err = GetLastError();
+        FIXME("pipe creation failed for %s, le is %u\n", debugstr_w(pipefn), GetLastError());
+        CloseHandle(lsp->stop_event);
+        HeapFree(GetProcessHeap(), 0, lsp);
+        return HRESULT_FROM_WIN32(err);
+    }
+
+    lsp->thread = CreateThread(NULL, 0, local_server_thread, lsp, 0, &tid);
+    if (!lsp->thread)
+    {
+        CloseHandle(lsp->pipe);
+        CloseHandle(lsp->stop_event);
+        HeapFree(GetProcessHeap(), 0, lsp);
+        return HRESULT_FROM_WIN32(GetLastError());
+    }
+
+    *registration = lsp;
+    return S_OK;
+}
+
+void rpc_stop_local_server(void *registration)
+{
+    struct local_server_params *lsp = registration;
+
+    /* signal local_server_thread to stop */
+    SetEvent(lsp->stop_event);
+    /* wait for it to exit */
+    WaitForSingleObject(lsp->thread, INFINITE);
+
+    IStream_Release(lsp->stream);
+    CloseHandle(lsp->stop_event);
+    CloseHandle(lsp->thread);
+    HeapFree(GetProcessHeap(), 0, lsp);
+}
diff --git a/dlls/ole32/compobj.c b/dlls/ole32/compobj.c
index 18580e9b235..ef9888d9e38 100644
--- a/dlls/ole32/compobj.c
+++ b/dlls/ole32/compobj.c
@@ -142,40 +142,6 @@ struct class_reg_data
     } u;
 };
 
-/* Reference count used by CoAddRefServerProcess/CoReleaseServerProcess */
-static LONG s_COMServerProcessReferences = 0;
-
-/*
- * This linked list contains the list of registered class objects. These
- * are mostly used to register the factories for out-of-proc servers of OLE
- * objects.
- *
- * TODO: Make this data structure aware of inter-process communication. This
- *       means that parts of this will be exported to rpcss.
- */
-typedef struct tagRegisteredClass
-{
-  struct list entry;
-  CLSID     classIdentifier;
-  OXID      apartment_id;
-  LPUNKNOWN classObject;
-  DWORD     runContext;
-  DWORD     connectFlags;
-  DWORD     dwCookie;
-  void     *RpcRegistration;
-} RegisteredClass;
-
-static struct list RegisteredClassList = LIST_INIT(RegisteredClassList);
-
-static CRITICAL_SECTION csRegisteredClassList;
-static CRITICAL_SECTION_DEBUG class_cs_debug =
-{
-    0, 0, &csRegisteredClassList,
-    { &class_cs_debug.ProcessLocksList, &class_cs_debug.ProcessLocksList },
-      0, 0, { (DWORD_PTR)(__FILE__ ": csRegisteredClassList") }
-};
-static CRITICAL_SECTION csRegisteredClassList = { &class_cs_debug, -1, 0, 0, 0, 0 };
-
 static inline enum comclass_miscfields dvaspect_to_miscfields(DWORD aspect)
 {
     switch (aspect)
@@ -374,32 +340,6 @@ LSTATUS open_classes_key( HKEY hkey, const WCHAR *name, REGSAM access, HKEY *ret
     return RtlNtStatusToDosError( NtOpenKey( (HANDLE *)retkey, access, &attr ) );
 }
 
-static void COM_RevokeRegisteredClassObject(RegisteredClass *curClass)
-{
-    list_remove(&curClass->entry);
-
-    if (curClass->runContext & CLSCTX_LOCAL_SERVER)
-        RPC_StopLocalServer(curClass->RpcRegistration);
-
-    IUnknown_Release(curClass->classObject);
-    HeapFree(GetProcessHeap(), 0, curClass);
-}
-
-void WINAPI InternalRevokeAllClasses(const struct apartment *apt)
-{
-  RegisteredClass *curClass, *cursor;
-
-  EnterCriticalSection( &csRegisteredClassList );
-
-  LIST_FOR_EACH_ENTRY_SAFE(curClass, cursor, &RegisteredClassList, RegisteredClass, entry)
-  {
-    if (curClass->apartment_id == apt->oxid)
-      COM_RevokeRegisteredClassObject(curClass);
-  }
-
-  LeaveCriticalSection( &csRegisteredClassList );
-}
-
 /******************************************************************************
  * Implementation of the manual reset event object. (CLSID_ManualResetEvent)
  */
@@ -549,69 +489,6 @@ HRESULT WINAPI ManualResetEvent_CreateInstance(IClassFactory *iface, IUnknown *o
     return hr;
 }
 
-/***********************************************************************
- *           CoRevokeClassObject [OLE32.@]
- *
- * Removes a class object from the class registry.
- *
- * PARAMS
- *  dwRegister [I] Cookie returned from CoRegisterClassObject().
- *
- * RETURNS
- *  Success: S_OK.
- *  Failure: HRESULT code.
- *
- * NOTES
- *  Must be called from the same apartment that called CoRegisterClassObject(),
- *  otherwise it will fail with RPC_E_WRONG_THREAD.
- *
- * SEE ALSO
- *  CoRegisterClassObject
- */
-HRESULT WINAPI DECLSPEC_HOTPATCH CoRevokeClassObject(
-        DWORD dwRegister)
-{
-  HRESULT hr = E_INVALIDARG;
-  RegisteredClass *curClass;
-  struct apartment *apt;
-
-  TRACE("(%08x)\n",dwRegister);
-
-  if (!(apt = apartment_get_current_or_mta()))
-  {
-    ERR("COM was not initialized\n");
-    return CO_E_NOTINITIALIZED;
-  }
-
-  EnterCriticalSection( &csRegisteredClassList );
-
-  LIST_FOR_EACH_ENTRY(curClass, &RegisteredClassList, RegisteredClass, entry)
-  {
-    /*
-     * Check if we have a match on the cookie.
-     */
-    if (curClass->dwCookie == dwRegister)
-    {
-      if (curClass->apartment_id == apt->oxid)
-      {
-          COM_RevokeRegisteredClassObject(curClass);
-          hr = S_OK;
-      }
-      else
-      {
-          ERR("called from wrong apartment, should be called from %s\n",
-              wine_dbgstr_longlong(curClass->apartment_id));
-          hr = RPC_E_WRONG_THREAD;
-      }
-      break;
-    }
-  }
-
-  LeaveCriticalSection( &csRegisteredClassList );
-  apartment_release(apt);
-  return hr;
-}
-
 static void COM_TlsDestroy(void)
 {
     struct oletls *info = NtCurrentTeb()->ReservedForOle;
@@ -772,182 +649,6 @@ HRESULT COM_OpenKeyForCLSID(REFCLSID clsid, LPCWSTR keyname, REGSAM access, HKEY
     return S_OK;
 }
 
-/***
- * This internal method is used to scan the registered class list to
- * find a class object.
- *
- * Params:
- *   rclsid        Class ID of the class to find.
- *   dwClsContext  Class context to match.
- *   ppv           [out] returns a pointer to the class object. Complying
- *                 to normal COM usage, this method will increase the
- *                 reference count on this object.
- */
-HRESULT WINAPI InternalGetRegisteredClassObject(const struct apartment *apt, REFCLSID rclsid,
-                                            DWORD dwClsContext, LPUNKNOWN* ppUnk)
-{
-  HRESULT hr = S_FALSE;
-  RegisteredClass *curClass;
-
-  EnterCriticalSection( &csRegisteredClassList );
-
-  LIST_FOR_EACH_ENTRY(curClass, &RegisteredClassList, RegisteredClass, entry)
-  {
-    /*
-     * Check if we have a match on the class ID and context.
-     */
-    if ((apt->oxid == curClass->apartment_id) &&
-        (dwClsContext & curClass->runContext) &&
-        IsEqualGUID(&(curClass->classIdentifier), rclsid))
-    {
-      /*
-       * We have a match, return the pointer to the class object.
-       */
-      *ppUnk = curClass->classObject;
-
-      IUnknown_AddRef(curClass->classObject);
-
-      hr = S_OK;
-      break;
-    }
-  }
-
-  LeaveCriticalSection( &csRegisteredClassList );
-
-  return hr;
-}
-
-/******************************************************************************
- *		CoRegisterClassObject	[OLE32.@]
- *
- * Registers the class object for a given class ID. Servers housed in EXE
- * files use this method instead of exporting DllGetClassObject to allow
- * other code to connect to their objects.
- *
- * PARAMS
- *  rclsid       [I] CLSID of the object to register.
- *  pUnk         [I] IUnknown of the object.
- *  dwClsContext [I] CLSCTX flags indicating the context in which to run the executable.
- *  flags        [I] REGCLS flags indicating how connections are made.
- *  lpdwRegister [I] A unique cookie that can be passed to CoRevokeClassObject.
- *
- * RETURNS
- *   S_OK on success,
- *   E_INVALIDARG if lpdwRegister or pUnk are NULL,
- *   CO_E_OBJISREG if the object is already registered. We should not return this.
- *
- * SEE ALSO
- *   CoRevokeClassObject, CoGetClassObject
- *
- * NOTES
- *  In-process objects are only registered for the current apartment.
- *  CoGetClassObject() and CoCreateInstance() will not return objects registered
- *  in other apartments.
- *
- * BUGS
- *  MSDN claims that multiple interface registrations are legal, but we
- *  can't do that with our current implementation.
- */
-HRESULT WINAPI CoRegisterClassObject(
-    REFCLSID rclsid,
-    LPUNKNOWN pUnk,
-    DWORD dwClsContext,
-    DWORD flags,
-    LPDWORD lpdwRegister)
-{
-  static LONG next_cookie;
-  RegisteredClass* newClass;
-  LPUNKNOWN        foundObject;
-  HRESULT          hr;
-  struct apartment *apt;
-
-  TRACE("(%s,%p,0x%08x,0x%08x,%p)\n",
-	debugstr_guid(rclsid),pUnk,dwClsContext,flags,lpdwRegister);
-
-  if ( (lpdwRegister==0) || (pUnk==0) )
-    return E_INVALIDARG;
-
-  if (!(apt = apartment_get_current_or_mta()))
-  {
-      ERR("COM was not initialized\n");
-      return CO_E_NOTINITIALIZED;
-  }
-
-  *lpdwRegister = 0;
-
-  /* REGCLS_MULTIPLEUSE implies registering as inproc server. This is what
-   * differentiates the flag from REGCLS_MULTI_SEPARATE. */
-  if (flags & REGCLS_MULTIPLEUSE)
-    dwClsContext |= CLSCTX_INPROC_SERVER;
-
-  /*
-   * First, check if the class is already registered.
-   * If it is, this should cause an error.
-   */
-  hr = InternalGetRegisteredClassObject(apt, rclsid, dwClsContext, &foundObject);
-  if (hr == S_OK) {
-    if (flags & REGCLS_MULTIPLEUSE) {
-      if (dwClsContext & CLSCTX_LOCAL_SERVER)
-        hr = CoLockObjectExternal(foundObject, TRUE, FALSE);
-      IUnknown_Release(foundObject);
-      apartment_release(apt);
-      return hr;
-    }
-    IUnknown_Release(foundObject);
-    ERR("object already registered for class %s\n", debugstr_guid(rclsid));
-    apartment_release(apt);
-    return CO_E_OBJISREG;
-  }
-
-  newClass = HeapAlloc(GetProcessHeap(), 0, sizeof(RegisteredClass));
-  if ( newClass == NULL )
-  {
-    apartment_release(apt);
-    return E_OUTOFMEMORY;
-  }
-
-  newClass->classIdentifier = *rclsid;
-  newClass->apartment_id    = apt->oxid;
-  newClass->runContext      = dwClsContext;
-  newClass->connectFlags    = flags;
-  newClass->RpcRegistration = NULL;
-
-  if (!(newClass->dwCookie = InterlockedIncrement( &next_cookie )))
-      newClass->dwCookie = InterlockedIncrement( &next_cookie );
-
-  /*
-   * Since we're making a copy of the object pointer, we have to increase its
-   * reference count.
-   */
-  newClass->classObject     = pUnk;
-  IUnknown_AddRef(newClass->classObject);
-
-  EnterCriticalSection( &csRegisteredClassList );
-  list_add_tail(&RegisteredClassList, &newClass->entry);
-  LeaveCriticalSection( &csRegisteredClassList );
-
-  *lpdwRegister = newClass->dwCookie;
-
-  if (dwClsContext & CLSCTX_LOCAL_SERVER) {
-      IStream *marshal_stream;
-
-      hr = apartment_get_local_server_stream(apt, &marshal_stream);
-      if(FAILED(hr))
-      {
-          apartment_release(apt);
-          return hr;
-      }
-
-      hr = RPC_StartLocalServer(&newClass->classIdentifier,
-                                marshal_stream,
-                                flags & (REGCLS_MULTIPLEUSE|REGCLS_MULTI_SEPARATE),
-                                &newClass->RpcRegistration);
-      IStream_Release(marshal_stream);
-  }
-  apartment_release(apt);
-  return S_OK;
-}
-
 /***********************************************************************
  *        CoResumeClassObjects (OLE32.@)
  *
@@ -1295,67 +996,6 @@ HRESULT WINAPI CoSuspendClassObjects(void)
     return S_OK;
 }
 
-/***********************************************************************
- *           CoAddRefServerProcess [OLE32.@]
- *
- * Helper function for incrementing the reference count of a local-server
- * process.
- *
- * RETURNS
- *  New reference count.
- *
- * SEE ALSO
- *  CoReleaseServerProcess().
- */
-ULONG WINAPI CoAddRefServerProcess(void)
-{
-    ULONG refs;
-
-    TRACE("\n");
-
-    EnterCriticalSection(&csRegisteredClassList);
-    refs = ++s_COMServerProcessReferences;
-    LeaveCriticalSection(&csRegisteredClassList);
-
-    TRACE("refs before: %d\n", refs - 1);
-
-    return refs;
-}
-
-/***********************************************************************
- *           CoReleaseServerProcess [OLE32.@]
- *
- * Helper function for decrementing the reference count of a local-server
- * process.
- *
- * RETURNS
- *  New reference count.
- *
- * NOTES
- *  When reference count reaches 0, this function suspends all registered
- *  classes so no new connections are accepted.
- *
- * SEE ALSO
- *  CoAddRefServerProcess(), CoSuspendClassObjects().
- */
-ULONG WINAPI CoReleaseServerProcess(void)
-{
-    ULONG refs;
-
-    TRACE("\n");
-
-    EnterCriticalSection(&csRegisteredClassList);
-
-    refs = --s_COMServerProcessReferences;
-    /* FIXME: if (!refs) COM_SuspendClassObjects(); */
-
-    LeaveCriticalSection(&csRegisteredClassList);
-
-    TRACE("refs after: %d\n", refs);
-
-    return refs;
-}
-
 /***********************************************************************
  *           CoIsHandlerConnected [OLE32.@]
  *
@@ -1683,7 +1323,6 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID reserved)
         if (reserved) break;
         release_std_git();
         RPC_UnregisterAllChannelHooks();
-        DeleteCriticalSection(&csRegisteredClassList);
         apartment_global_cleanup();
         break;
 
diff --git a/dlls/ole32/compobj_private.h b/dlls/ole32/compobj_private.h
index 7a571352d32..e68d7b3b3da 100644
--- a/dlls/ole32/compobj_private.h
+++ b/dlls/ole32/compobj_private.h
@@ -223,12 +223,8 @@ HRESULT RPC_CreateClientChannel(const OXID *oxid, const IPID *ipid,
                                 DWORD dest_context, void *dest_context_data,
                                 IRpcChannelBuffer **chan, struct apartment *apt) DECLSPEC_HIDDEN;
 HRESULT RPC_CreateServerChannel(DWORD dest_context, void *dest_context_data, IRpcChannelBuffer **chan) DECLSPEC_HIDDEN;
-void    RPC_ExecuteCall(struct dispatch_params *params) DECLSPEC_HIDDEN;
 HRESULT RPC_RegisterInterface(REFIID riid) DECLSPEC_HIDDEN;
 void    RPC_UnregisterInterface(REFIID riid, BOOL wait) DECLSPEC_HIDDEN;
-HRESULT RPC_StartLocalServer(REFCLSID clsid, IStream *stream, BOOL multi_use, void **registration) DECLSPEC_HIDDEN;
-void    RPC_StopLocalServer(void *registration) DECLSPEC_HIDDEN;
-HRESULT RPC_GetLocalClassObject(REFCLSID rclsid, REFIID iid, LPVOID *ppv) DECLSPEC_HIDDEN;
 HRESULT RPC_RegisterChannelHook(REFGUID rguid, IChannelHook *hook) DECLSPEC_HIDDEN;
 void    RPC_UnregisterAllChannelHooks(void) DECLSPEC_HIDDEN;
 HRESULT RPC_ResolveOxid(OXID oxid, OXID_INFO *oxid_info) DECLSPEC_HIDDEN;
@@ -254,10 +250,6 @@ extern struct apartment * WINAPI apartment_get_current_or_mta(void) DECLSPEC_HID
 extern HRESULT WINAPI apartment_get_local_server_stream(struct apartment *apt, IStream **ret) DECLSPEC_HIDDEN;
 extern void WINAPI apartment_global_cleanup(void) DECLSPEC_HIDDEN;
 
-HRESULT COM_GetRegisteredClassObject(const struct apartment *apt, REFCLSID rclsid,
-        DWORD dwClsContext, IUnknown **ppUnk) DECLSPEC_HIDDEN;
-void COM_RevokeAllClasses(const struct apartment *apt) DECLSPEC_HIDDEN;
-
 /* DCOM messages used by the apartment window (not compatible with native) */
 #define DM_EXECUTERPC   (WM_USER + 0) /* WPARAM = 0, LPARAM = (struct dispatch_params *) */
 #define DM_HOSTOBJECT   (WM_USER + 1) /* WPARAM = 0, LPARAM = (struct host_object_params *) */
diff --git a/dlls/ole32/ole32.spec b/dlls/ole32/ole32.spec
index c4e7b594fb2..ca22e4c8f1a 100644
--- a/dlls/ole32/ole32.spec
+++ b/dlls/ole32/ole32.spec
@@ -6,7 +6,7 @@
 @ stdcall CLSIDFromProgID(wstr ptr) combase.CLSIDFromProgID
 @ stdcall CLSIDFromProgIDEx(wstr ptr) combase.CLSIDFromProgIDEx
 @ stdcall CLSIDFromString(wstr ptr) combase.CLSIDFromString
-@ stdcall CoAddRefServerProcess()
+@ stdcall CoAddRefServerProcess() combase.CoAddRefServerProcess
 @ stdcall CoAllowSetForegroundWindow(ptr ptr)
 @ stdcall CoBuildVersion()
 @ stdcall CoCopyProxy(ptr ptr) combase.CoCopyProxy
@@ -65,7 +65,7 @@
 @ stdcall CoQueryProxyBlanket(ptr ptr ptr ptr ptr ptr ptr ptr) combase.CoQueryProxyBlanket
 @ stub CoQueryReleaseObject
 @ stdcall CoRegisterChannelHook(ptr ptr)
-@ stdcall CoRegisterClassObject(ptr ptr long long ptr)
+@ stdcall CoRegisterClassObject(ptr ptr long long ptr) combase.CoRegisterClassObject
 @ stdcall CoRegisterInitializeSpy(ptr ptr) combase.CoRegisterInitializeSpy
 @ stdcall CoRegisterMallocSpy(ptr) combase.CoRegisterMallocSpy
 @ stdcall CoRegisterMessageFilter(ptr ptr) combase.CoRegisterMessageFilter
@@ -73,10 +73,10 @@
 @ stdcall CoRegisterSurrogate(ptr)
 @ stdcall CoRegisterSurrogateEx(ptr ptr)
 @ stdcall CoReleaseMarshalData(ptr)
-@ stdcall CoReleaseServerProcess()
+@ stdcall CoReleaseServerProcess() combase.CoReleaseServerProcess
 @ stdcall CoResumeClassObjects()
 @ stdcall CoRevertToSelf() combase.CoRevertToSelf
-@ stdcall CoRevokeClassObject(long)
+@ stdcall CoRevokeClassObject(long) combase.CoRevokeClassObject
 @ stdcall CoRevokeInitializeSpy(int64) combase.CoRevokeInitializeSpy
 @ stdcall CoRevokeMallocSpy() combase.CoRevokeMallocSpy
 @ stdcall CoSetProxyBlanket(ptr long long ptr long long ptr long) combase.CoSetProxyBlanket
@@ -298,8 +298,6 @@
 @ stdcall WriteFmtUserTypeStg(ptr long ptr)
 @ stub WriteOleStg
 @ stub WriteStringStream
-@ stdcall InternalGetRegisteredClassObject(ptr ptr long ptr)
-@ stdcall InternalRevokeAllClasses(ptr)
 @ stdcall Internal_apartment_disconnectproxies(ptr)
 @ stdcall Internal_RPC_ExecuteCall(ptr)
 @ stdcall Internal_stub_manager_int_release(ptr)
diff --git a/dlls/ole32/rpc.c b/dlls/ole32/rpc.c
index eb76d9cb668..84d26c70c6c 100644
--- a/dlls/ole32/rpc.c
+++ b/dlls/ole32/rpc.c
@@ -1648,182 +1648,3 @@ void RPC_StartRemoting(struct apartment *apt)
     }
     start_apartment_remote_unknown(apt);
 }
-
-static void get_localserver_pipe_name(WCHAR *pipefn, REFCLSID rclsid)
-{
-    static const WCHAR wszPipeRef[] = {'\\','\\','.','\\','p','i','p','e','\\',0};
-    lstrcpyW(pipefn, wszPipeRef);
-    StringFromGUID2(rclsid, pipefn + ARRAY_SIZE(wszPipeRef) - 1, CHARS_IN_GUID);
-}
-
-struct local_server_params
-{
-    CLSID clsid;
-    IStream *stream;
-    HANDLE pipe;
-    HANDLE stop_event;
-    HANDLE thread;
-    BOOL multi_use;
-};
-
-/* FIXME: should call to rpcss instead */
-static DWORD WINAPI local_server_thread(LPVOID param)
-{
-    struct local_server_params * lsp = param;
-    WCHAR 		pipefn[100];
-    HRESULT		hres;
-    IStream		*pStm = lsp->stream;
-    STATSTG		ststg;
-    unsigned char	*buffer;
-    int 		buflen;
-    LARGE_INTEGER	seekto;
-    ULARGE_INTEGER	newpos;
-    ULONG		res;
-    BOOL multi_use = lsp->multi_use;
-    OVERLAPPED ovl;
-    HANDLE pipe_event, hPipe = lsp->pipe, new_pipe;
-    DWORD  bytes;
-
-    TRACE("Starting threader for %s.\n",debugstr_guid(&lsp->clsid));
-
-    memset(&ovl, 0, sizeof(ovl));
-    get_localserver_pipe_name(pipefn, &lsp->clsid);
-    ovl.hEvent = pipe_event = CreateEventW(NULL, FALSE, FALSE, NULL);
-
-    while (1) {
-        if (!ConnectNamedPipe(hPipe, &ovl))
-        {
-            DWORD error = GetLastError();
-            if (error == ERROR_IO_PENDING)
-            {
-                HANDLE handles[2] = { pipe_event, lsp->stop_event };
-                DWORD ret;
-                ret = WaitForMultipleObjects(2, handles, FALSE, INFINITE);
-                if (ret != WAIT_OBJECT_0)
-                    break;
-            }
-            /* client already connected isn't an error */
-            else if (error != ERROR_PIPE_CONNECTED)
-            {
-                ERR("ConnectNamedPipe failed with error %d\n", GetLastError());
-                break;
-            }
-        }
-
-        TRACE("marshalling LocalServer to client\n");
-        
-        hres = IStream_Stat(pStm,&ststg,STATFLAG_NONAME);
-        if (hres != S_OK)
-            break;
-
-        seekto.u.LowPart = 0;
-        seekto.u.HighPart = 0;
-        hres = IStream_Seek(pStm,seekto,STREAM_SEEK_SET,&newpos);
-        if (hres != S_OK) {
-            FIXME("IStream_Seek failed, %x\n",hres);
-            break;
-        }
-
-        buflen = ststg.cbSize.u.LowPart;
-        buffer = HeapAlloc(GetProcessHeap(),0,buflen);
-        
-        hres = IStream_Read(pStm,buffer,buflen,&res);
-        if (hres != S_OK) {
-            FIXME("Stream Read failed, %x\n",hres);
-            HeapFree(GetProcessHeap(),0,buffer);
-            break;
-        }
-        
-        WriteFile(hPipe,buffer,buflen,&res,&ovl);
-        GetOverlappedResult(hPipe, &ovl, &bytes, TRUE);
-        HeapFree(GetProcessHeap(),0,buffer);
-
-        FlushFileBuffers(hPipe);
-        DisconnectNamedPipe(hPipe);
-        TRACE("done marshalling LocalServer\n");
-
-        if (!multi_use)
-        {
-            TRACE("single use object, shutting down pipe %s\n", debugstr_w(pipefn));
-            break;
-        }
-        new_pipe = CreateNamedPipeW( pipefn, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
-                                     PIPE_TYPE_BYTE|PIPE_WAIT, PIPE_UNLIMITED_INSTANCES,
-                                     4096, 4096, 500 /* 0.5 second timeout */, NULL );
-        if (new_pipe == INVALID_HANDLE_VALUE)
-        {
-            FIXME("pipe creation failed for %s, le is %u\n", debugstr_w(pipefn), GetLastError());
-            break;
-        }
-        CloseHandle(hPipe);
-        hPipe = new_pipe;
-    }
-
-    CloseHandle(pipe_event);
-    CloseHandle(hPipe);
-    return 0;
-}
-
-/* starts listening for a local server */
-HRESULT RPC_StartLocalServer(REFCLSID clsid, IStream *stream, BOOL multi_use, void **registration)
-{
-    DWORD tid, err;
-    struct local_server_params *lsp;
-    WCHAR pipefn[100];
-
-    lsp = HeapAlloc(GetProcessHeap(), 0, sizeof(*lsp));
-    if (!lsp)
-        return E_OUTOFMEMORY;
-
-    lsp->clsid = *clsid;
-    lsp->stream = stream;
-    IStream_AddRef(stream);
-    lsp->stop_event = CreateEventW(NULL, FALSE, FALSE, NULL);
-    if (!lsp->stop_event)
-    {
-        HeapFree(GetProcessHeap(), 0, lsp);
-        return HRESULT_FROM_WIN32(GetLastError());
-    }
-    lsp->multi_use = multi_use;
-
-    get_localserver_pipe_name(pipefn, &lsp->clsid);
-    lsp->pipe = CreateNamedPipeW(pipefn, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
-                                 PIPE_TYPE_BYTE|PIPE_WAIT, PIPE_UNLIMITED_INSTANCES,
-                                 4096, 4096, 500 /* 0.5 second timeout */, NULL);
-    if (lsp->pipe == INVALID_HANDLE_VALUE)
-    {
-        err = GetLastError();
-        FIXME("pipe creation failed for %s, le is %u\n", debugstr_w(pipefn), GetLastError());
-        CloseHandle(lsp->stop_event);
-        HeapFree(GetProcessHeap(), 0, lsp);
-        return HRESULT_FROM_WIN32(err);
-    }
-
-    lsp->thread = CreateThread(NULL, 0, local_server_thread, lsp, 0, &tid);
-    if (!lsp->thread)
-    {
-        CloseHandle(lsp->pipe);
-        CloseHandle(lsp->stop_event);
-        HeapFree(GetProcessHeap(), 0, lsp);
-        return HRESULT_FROM_WIN32(GetLastError());
-    }
-
-    *registration = lsp;
-    return S_OK;
-}
-
-/* stops listening for a local server */
-void RPC_StopLocalServer(void *registration)
-{
-    struct local_server_params *lsp = registration;
-
-    /* signal local_server_thread to stop */
-    SetEvent(lsp->stop_event);
-    /* wait for it to exit */
-    WaitForSingleObject(lsp->thread, INFINITE);
-
-    IStream_Release(lsp->stream);
-    CloseHandle(lsp->stop_event);
-    CloseHandle(lsp->thread);
-    HeapFree(GetProcessHeap(), 0, lsp);
-}
-- 
2.28.0




More information about the wine-devel mailing list