Commit 24723913 authored by Rob Shearman's avatar Rob Shearman Committed by Alexandre Julliard

ole32: Use asynchronous I/O for the named pipe server for local servers.

parent da040186
...@@ -1712,7 +1712,7 @@ HRESULT RPC_GetLocalClassObject(REFCLSID rclsid, REFIID iid, LPVOID *ppv) ...@@ -1712,7 +1712,7 @@ HRESULT RPC_GetLocalClassObject(REFCLSID rclsid, REFIID iid, LPVOID *ppv)
while (tries++ < MAXTRIES) { while (tries++ < MAXTRIES) {
TRACE("waiting for %s\n", debugstr_w(pipefn)); TRACE("waiting for %s\n", debugstr_w(pipefn));
WaitNamedPipeW( pipefn, NMPWAIT_WAIT_FOREVER ); WaitNamedPipeW( pipefn, NMPWAIT_WAIT_FOREVER );
hPipe = CreateFileW(pipefn, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0); hPipe = CreateFileW(pipefn, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
if (hPipe == INVALID_HANDLE_VALUE) { if (hPipe == INVALID_HANDLE_VALUE) {
...@@ -1761,8 +1761,9 @@ struct local_server_params ...@@ -1761,8 +1761,9 @@ struct local_server_params
CLSID clsid; CLSID clsid;
IStream *stream; IStream *stream;
HANDLE ready_event; HANDLE ready_event;
HANDLE stop_event;
HANDLE thread;
BOOL multi_use; BOOL multi_use;
HANDLE pipe;
}; };
/* FIXME: should call to rpcss instead */ /* FIXME: should call to rpcss instead */
...@@ -1780,40 +1781,44 @@ static DWORD WINAPI local_server_thread(LPVOID param) ...@@ -1780,40 +1781,44 @@ static DWORD WINAPI local_server_thread(LPVOID param)
ULARGE_INTEGER newpos; ULARGE_INTEGER newpos;
ULONG res; ULONG res;
BOOL multi_use = lsp->multi_use; BOOL multi_use = lsp->multi_use;
OVERLAPPED ovl;
HANDLE pipe_event;
TRACE("Starting threader for %s.\n",debugstr_guid(&lsp->clsid)); TRACE("Starting threader for %s.\n",debugstr_guid(&lsp->clsid));
memset(&ovl, 0, sizeof(ovl));
get_localserver_pipe_name(pipefn, &lsp->clsid); 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, PIPE_TYPE_BYTE|PIPE_WAIT, PIPE_UNLIMITED_INSTANCES,
4096, 4096, 500 /* 0.5 second timeout */, NULL ); 4096, 4096, 500 /* 0.5 second timeout */, NULL );
lsp->pipe = hPipe;
SetEvent(lsp->ready_event); SetEvent(lsp->ready_event);
HeapFree(GetProcessHeap(), 0, lsp);
if (hPipe == INVALID_HANDLE_VALUE) if (hPipe == INVALID_HANDLE_VALUE)
{ {
FIXME("pipe creation failed for %s, le is %u\n", debugstr_w(pipefn), GetLastError()); FIXME("pipe creation failed for %s, le is %u\n", debugstr_w(pipefn), GetLastError());
return 1; return 1;
} }
ovl.hEvent = pipe_event = CreateEventW(NULL, FALSE, FALSE, NULL);
while (1) { while (1) {
if (!ConnectNamedPipe(hPipe,NULL)) if (!ConnectNamedPipe(hPipe, &ovl))
{ {
DWORD error = GetLastError(); 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 */ /* 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 ERR("ConnectNamedPipe failed with error %d\n", GetLastError());
* pipe for us */
if (error != ERROR_INVALID_HANDLE)
{
ERR("Failure during ConnectNamedPipe %u\n", error);
CloseHandle(hPipe);
}
break; break;
} }
} }
...@@ -1828,6 +1833,8 @@ static DWORD WINAPI local_server_thread(LPVOID param) ...@@ -1828,6 +1833,8 @@ static DWORD WINAPI local_server_thread(LPVOID param)
hres = IStream_Seek(pStm,seekto,SEEK_SET,&newpos); hres = IStream_Seek(pStm,seekto,SEEK_SET,&newpos);
if (hres) { if (hres) {
FIXME("IStream_Seek failed, %x\n",hres); FIXME("IStream_Seek failed, %x\n",hres);
CloseHandle(hPipe);
CloseHandle(pipe_event);
return hres; return hres;
} }
...@@ -1837,11 +1844,14 @@ static DWORD WINAPI local_server_thread(LPVOID param) ...@@ -1837,11 +1844,14 @@ static DWORD WINAPI local_server_thread(LPVOID param)
hres = IStream_Read(pStm,buffer,buflen,&res); hres = IStream_Read(pStm,buffer,buflen,&res);
if (hres) { if (hres) {
FIXME("Stream Read failed, %x\n",hres); FIXME("Stream Read failed, %x\n",hres);
CloseHandle(hPipe);
CloseHandle(pipe_event);
HeapFree(GetProcessHeap(),0,buffer); HeapFree(GetProcessHeap(),0,buffer);
return hres; return hres;
} }
WriteFile(hPipe,buffer,buflen,&res,NULL); WriteFile(hPipe,buffer,buflen,&res,&ovl);
GetOverlappedResult(hPipe, &ovl, NULL, TRUE);
HeapFree(GetProcessHeap(),0,buffer); HeapFree(GetProcessHeap(),0,buffer);
FlushFileBuffers(hPipe); FlushFileBuffers(hPipe);
...@@ -1852,11 +1862,11 @@ static DWORD WINAPI local_server_thread(LPVOID param) ...@@ -1852,11 +1862,11 @@ static DWORD WINAPI local_server_thread(LPVOID param)
if (!multi_use) if (!multi_use)
{ {
TRACE("single use object, shutting down pipe %s\n", debugstr_w(pipefn)); TRACE("single use object, shutting down pipe %s\n", debugstr_w(pipefn));
CloseHandle(hPipe);
break; break;
} }
} }
IStream_Release(pStm); CloseHandle(hPipe);
CloseHandle(pipe_event);
return 0; return 0;
} }
...@@ -1864,30 +1874,59 @@ static DWORD WINAPI local_server_thread(LPVOID param) ...@@ -1864,30 +1874,59 @@ static DWORD WINAPI local_server_thread(LPVOID param)
HRESULT RPC_StartLocalServer(REFCLSID clsid, IStream *stream, BOOL multi_use, void **registration) HRESULT RPC_StartLocalServer(REFCLSID clsid, IStream *stream, BOOL multi_use, void **registration)
{ {
DWORD tid; DWORD tid;
HANDLE thread, ready_event; struct local_server_params *lsp;
struct local_server_params *lsp = HeapAlloc(GetProcessHeap(), 0, sizeof(*lsp));
lsp = HeapAlloc(GetProcessHeap(), 0, sizeof(*lsp));
if (!lsp)
return E_OUTOFMEMORY;
lsp->clsid = *clsid; lsp->clsid = *clsid;
lsp->stream = stream; lsp->stream = stream;
IStream_AddRef(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; lsp->multi_use = multi_use;
thread = CreateThread(NULL, 0, local_server_thread, lsp, 0, &tid); lsp->thread = CreateThread(NULL, 0, local_server_thread, lsp, 0, &tid);
if (!thread) if (!lsp->thread)
{
CloseHandle(lsp->ready_event);
CloseHandle(lsp->stop_event);
HeapFree(GetProcessHeap(), 0, lsp);
return HRESULT_FROM_WIN32(GetLastError()); return HRESULT_FROM_WIN32(GetLastError());
CloseHandle(thread); }
WaitForSingleObject(ready_event, INFINITE); WaitForSingleObject(lsp->ready_event, INFINITE);
CloseHandle(ready_event); CloseHandle(lsp->ready_event);
lsp->ready_event = NULL;
*registration = lsp->pipe; *registration = lsp;
return S_OK; return S_OK;
} }
/* stops listening for a local server */ /* stops listening for a local server */
void RPC_StopLocalServer(void *registration) void RPC_StopLocalServer(void *registration)
{ {
HANDLE pipe = registration; struct local_server_params *lsp = registration;
CloseHandle(pipe);
/* 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);
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment