Rob Shearman : ole32: Use asynchronous I/ O for the named pipe server for local servers.
Alexandre Julliard
julliard at winehq.org
Tue Nov 13 08:34:43 CST 2007
Module: wine
Branch: master
Commit: 24723913e08674d80bb41a13d38febbfa7bfd314
URL: http://source.winehq.org/git/wine.git/?a=commit;h=24723913e08674d80bb41a13d38febbfa7bfd314
Author: Rob Shearman <rob at codeweavers.com>
Date: Mon Nov 12 20:13:41 2007 +0000
ole32: Use asynchronous I/O for the named pipe server for local servers.
---
dlls/ole32/rpc.c | 97 +++++++++++++++++++++++++++++++++++++----------------
1 files changed, 68 insertions(+), 29 deletions(-)
diff --git a/dlls/ole32/rpc.c b/dlls/ole32/rpc.c
index 9c3ab83..57570c1 100644
--- a/dlls/ole32/rpc.c
+++ b/dlls/ole32/rpc.c
@@ -1712,7 +1712,7 @@ HRESULT RPC_GetLocalClassObject(REFCLSID rclsid, REFIID iid, LPVOID *ppv)
while (tries++ < MAXTRIES) {
TRACE("waiting for %s\n", debugstr_w(pipefn));
-
+
WaitNamedPipeW( pipefn, NMPWAIT_WAIT_FOREVER );
hPipe = CreateFileW(pipefn, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
if (hPipe == INVALID_HANDLE_VALUE) {
@@ -1761,8 +1761,9 @@ struct local_server_params
CLSID clsid;
IStream *stream;
HANDLE ready_event;
+ HANDLE stop_event;
+ HANDLE thread;
BOOL multi_use;
- HANDLE pipe;
};
/* FIXME: should call to rpcss instead */
@@ -1780,40 +1781,44 @@ static DWORD WINAPI local_server_thread(LPVOID param)
ULARGE_INTEGER newpos;
ULONG res;
BOOL multi_use = lsp->multi_use;
+ OVERLAPPED ovl;
+ HANDLE pipe_event;
TRACE("Starting threader for %s.\n",debugstr_guid(&lsp->clsid));
+ memset(&ovl, 0, sizeof(ovl));
get_localserver_pipe_name(pipefn, &lsp->clsid);
- hPipe = CreateNamedPipeW( pipefn, PIPE_ACCESS_DUPLEX,
+ hPipe = CreateNamedPipeW( pipefn, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
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);
-
if (hPipe == INVALID_HANDLE_VALUE)
{
FIXME("pipe creation failed for %s, le is %u\n", debugstr_w(pipefn), GetLastError());
return 1;
}
+
+ ovl.hEvent = pipe_event = CreateEventW(NULL, FALSE, FALSE, NULL);
while (1) {
- if (!ConnectNamedPipe(hPipe,NULL))
+ 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 */
- if (error != ERROR_PIPE_CONNECTED)
+ else 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);
- }
+ ERR("ConnectNamedPipe failed with error %d\n", GetLastError());
break;
}
}
@@ -1828,6 +1833,8 @@ static DWORD WINAPI local_server_thread(LPVOID param)
hres = IStream_Seek(pStm,seekto,SEEK_SET,&newpos);
if (hres) {
FIXME("IStream_Seek failed, %x\n",hres);
+ CloseHandle(hPipe);
+ CloseHandle(pipe_event);
return hres;
}
@@ -1837,11 +1844,14 @@ static DWORD WINAPI local_server_thread(LPVOID param)
hres = IStream_Read(pStm,buffer,buflen,&res);
if (hres) {
FIXME("Stream Read failed, %x\n",hres);
+ CloseHandle(hPipe);
+ CloseHandle(pipe_event);
HeapFree(GetProcessHeap(),0,buffer);
return hres;
}
- WriteFile(hPipe,buffer,buflen,&res,NULL);
+ WriteFile(hPipe,buffer,buflen,&res,&ovl);
+ GetOverlappedResult(hPipe, &ovl, NULL, TRUE);
HeapFree(GetProcessHeap(),0,buffer);
FlushFileBuffers(hPipe);
@@ -1852,11 +1862,11 @@ static DWORD WINAPI local_server_thread(LPVOID param)
if (!multi_use)
{
TRACE("single use object, shutting down pipe %s\n", debugstr_w(pipefn));
- CloseHandle(hPipe);
break;
}
}
- IStream_Release(pStm);
+ CloseHandle(hPipe);
+ CloseHandle(pipe_event);
return 0;
}
@@ -1864,30 +1874,59 @@ static DWORD WINAPI local_server_thread(LPVOID param)
HRESULT RPC_StartLocalServer(REFCLSID clsid, IStream *stream, BOOL multi_use, void **registration)
{
DWORD tid;
- HANDLE thread, ready_event;
- struct local_server_params *lsp = HeapAlloc(GetProcessHeap(), 0, sizeof(*lsp));
+ struct local_server_params *lsp;
+
+ lsp = HeapAlloc(GetProcessHeap(), 0, sizeof(*lsp));
+ if (!lsp)
+ return E_OUTOFMEMORY;
lsp->clsid = *clsid;
lsp->stream = stream;
IStream_AddRef(stream);
- lsp->ready_event = ready_event = CreateEventW(NULL, FALSE, FALSE, NULL);
+ lsp->ready_event = CreateEventW(NULL, FALSE, FALSE, NULL);
+ if (!lsp->ready_event)
+ {
+ HeapFree(GetProcessHeap(), 0, lsp);
+ return HRESULT_FROM_WIN32(GetLastError());
+ }
+ lsp->stop_event = CreateEventW(NULL, FALSE, FALSE, NULL);
+ if (!lsp->stop_event)
+ {
+ CloseHandle(lsp->ready_event);
+ HeapFree(GetProcessHeap(), 0, lsp);
+ return HRESULT_FROM_WIN32(GetLastError());
+ }
lsp->multi_use = multi_use;
- thread = CreateThread(NULL, 0, local_server_thread, lsp, 0, &tid);
- if (!thread)
+ lsp->thread = CreateThread(NULL, 0, local_server_thread, lsp, 0, &tid);
+ if (!lsp->thread)
+ {
+ CloseHandle(lsp->ready_event);
+ CloseHandle(lsp->stop_event);
+ HeapFree(GetProcessHeap(), 0, lsp);
return HRESULT_FROM_WIN32(GetLastError());
- CloseHandle(thread);
+ }
- WaitForSingleObject(ready_event, INFINITE);
- CloseHandle(ready_event);
+ WaitForSingleObject(lsp->ready_event, INFINITE);
+ CloseHandle(lsp->ready_event);
+ lsp->ready_event = NULL;
- *registration = lsp->pipe;
+ *registration = lsp;
return S_OK;
}
/* stops listening for a local server */
void RPC_StopLocalServer(void *registration)
{
- HANDLE pipe = registration;
- CloseHandle(pipe);
+ 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);
}
More information about the wine-cvs
mailing list