[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, ®istered_classes_cs,
+ { ®istered_classes_cs_debug.ProcessLocksList, ®istered_classes_cs_debug.ProcessLocksList },
+ 0, 0, { (DWORD_PTR)(__FILE__ ": registered_classes_cs") }
+};
+static CRITICAL_SECTION registered_classes_cs = { ®istered_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(®istered_classes_cs);
+
+ LIST_FOR_EACH_ENTRY(cur, ®istered_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(®istered_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, ®ClassObject) == 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(®istered_classes_cs);
+ list_add_tail(®istered_classes, &newclass->entry);
+ LeaveCriticalSection(®istered_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(®istered_classes_cs);
+
+ LIST_FOR_EACH_ENTRY_SAFE(cur, cur2, ®istered_classes, struct registered_class, entry)
+ {
+ if (cur->apartment_id == apt->oxid)
+ com_revoke_class_object(cur);
+ }
+
+ LeaveCriticalSection(®istered_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(®istered_classes_cs);
+
+ LIST_FOR_EACH_ENTRY(cur, ®istered_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(®istered_classes_cs);
+ apartment_release(apt);
+
+ return hr;
+}
+
+/***********************************************************************
+ * CoAddRefServerProcess (combase.@)
+ */
+ULONG WINAPI CoAddRefServerProcess(void)
+{
+ ULONG refs;
+
+ TRACE("\n");
+
+ EnterCriticalSection(®istered_classes_cs);
+ refs = ++com_server_process_refcount;
+ LeaveCriticalSection(®istered_classes_cs);
+
+ TRACE("refs before: %d\n", refs - 1);
+
+ return refs;
+}
+
+/***********************************************************************
+ * CoReleaseServerProcess [OLE32.@]
+ */
+ULONG WINAPI CoReleaseServerProcess(void)
+{
+ ULONG refs;
+
+ TRACE("\n");
+
+ EnterCriticalSection(®istered_classes_cs);
+
+ refs = --com_server_process_refcount;
+ /* FIXME: suspend objects */
+
+ LeaveCriticalSection(®istered_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(®istered_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