From 880542a9f87ec7a2b023753f7e192582b478737f Mon Sep 17 00:00:00 2001 From: Rob Shearman Date: Fri, 9 Mar 2007 17:42:34 +0000 Subject: [PATCH] ole32: Close the named pipe after revoking local server objects. --- dlls/ole32/compobj.c | 9 ++++++++- dlls/ole32/compobj_private.h | 3 ++- dlls/ole32/rpc.c | 37 ++++++++++++++++++++++++++++++------ 3 files changed, 41 insertions(+), 8 deletions(-) diff --git a/dlls/ole32/compobj.c b/dlls/ole32/compobj.c index bac067a5695..98ec995a4b0 100644 --- a/dlls/ole32/compobj.c +++ b/dlls/ole32/compobj.c @@ -123,6 +123,7 @@ typedef struct tagRegisteredClass DWORD connectFlags; DWORD dwCookie; LPSTREAM pMarshaledData; /* FIXME: only really need to store OXID and IPID */ + void *RpcRegistration; struct tagRegisteredClass* nextClass; } RegisteredClass; @@ -1574,6 +1575,7 @@ HRESULT WINAPI CoRegisterClassObject( newClass->runContext = dwClsContext; newClass->connectFlags = flags; newClass->pMarshaledData = NULL; + newClass->RpcRegistration = NULL; /* * Use the address of the chain node as the cookie since we are sure it's @@ -1618,7 +1620,9 @@ HRESULT WINAPI CoRegisterClassObject( IUnknown_Release(classfac); - RPC_StartLocalServer(&newClass->classIdentifier, newClass->pMarshaledData); + hr = RPC_StartLocalServer(&newClass->classIdentifier, + newClass->pMarshaledData, + &newClass->RpcRegistration); } return S_OK; } @@ -1667,6 +1671,9 @@ HRESULT WINAPI CoRevokeClassObject( */ *prevClassLink = curClass->nextClass; + if (curClass->runContext & CLSCTX_LOCAL_SERVER) + RPC_StopLocalServer(curClass->RpcRegistration); + /* * Release the reference to the class object. */ diff --git a/dlls/ole32/compobj_private.h b/dlls/ole32/compobj_private.h index b77e05ff39e..4c96a3cd4c5 100644 --- a/dlls/ole32/compobj_private.h +++ b/dlls/ole32/compobj_private.h @@ -221,7 +221,8 @@ HRESULT RPC_CreateServerChannel(IRpcChannelBuffer **chan); void RPC_ExecuteCall(struct dispatch_params *params); HRESULT RPC_RegisterInterface(REFIID riid); void RPC_UnregisterInterface(REFIID riid); -void RPC_StartLocalServer(REFCLSID clsid, IStream *stream); +HRESULT RPC_StartLocalServer(REFCLSID clsid, IStream *stream, void **registration); +void RPC_StopLocalServer(void *registration); HRESULT RPC_GetLocalClassObject(REFCLSID rclsid, REFIID iid, LPVOID *ppv); HRESULT RPC_RegisterChannelHook(REFGUID rguid, IChannelHook *hook); void RPC_UnregisterAllChannelHooks(void); diff --git a/dlls/ole32/rpc.c b/dlls/ole32/rpc.c index fdb81edd3d0..3320552dba2 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; + HANDLE pipe; }; /* FIXME: should call to rpcss instead */ @@ -1757,6 +1758,7 @@ static DWORD WINAPI local_server_thread(LPVOID param) PIPE_TYPE_BYTE|PIPE_WAIT, PIPE_UNLIMITED_INSTANCES, 4096, 4096, 500 /* 0.5 second timeout */, NULL ); + lsp->pipe = hPipe; SetEvent(lsp->ready_event); HeapFree(GetProcessHeap(), 0, lsp); @@ -1768,9 +1770,21 @@ static DWORD WINAPI local_server_thread(LPVOID param) } while (1) { - if (!ConnectNamedPipe(hPipe,NULL) && GetLastError() != ERROR_PIPE_CONNECTED) { - ERR("Failure during ConnectNamedPipe %u, ABORT!\n",GetLastError()); - break; + if (!ConnectNamedPipe(hPipe,NULL)) + { + DWORD error = GetLastError(); + /* client already connected isn't an error */ + if (error != ERROR_PIPE_CONNECTED) + { + /* if error wasn't caused by RPC_StopLocalServer closing the + * pipe for us */ + if (error != ERROR_INVALID_HANDLE) + { + ERR("Failure during ConnectNamedPipe %u\n", error); + CloseHandle(hPipe); + } + break; + } } TRACE("marshalling IClassFactory to client\n"); @@ -1804,12 +1818,12 @@ static DWORD WINAPI local_server_thread(LPVOID param) TRACE("done marshalling IClassFactory\n"); } - CloseHandle(hPipe); IStream_Release(pStm); return 0; } -void RPC_StartLocalServer(REFCLSID clsid, IStream *stream) +/* starts listening for a local server */ +HRESULT RPC_StartLocalServer(REFCLSID clsid, IStream *stream, void **registration) { DWORD tid; HANDLE thread, ready_event; @@ -1821,9 +1835,20 @@ void RPC_StartLocalServer(REFCLSID clsid, IStream *stream) lsp->ready_event = ready_event = CreateEventW(NULL, FALSE, FALSE, NULL); thread = CreateThread(NULL, 0, local_server_thread, lsp, 0, &tid); + if (!thread) + return HRESULT_FROM_WIN32(GetLastError()); CloseHandle(thread); - /* FIXME: failure handling */ WaitForSingleObject(ready_event, INFINITE); CloseHandle(ready_event); + + *registration = lsp->pipe; + return S_OK; +} + +/* stops listening for a local server */ +void RPC_StopLocalServer(void *registration) +{ + HANDLE pipe = registration; + CloseHandle(pipe); }