From f0db7ab06b8851e58071b50baea9833746a8ee7c Mon Sep 17 00:00:00 2001 From: Ivan Leo Puoti Date: Tue, 6 Sep 2005 14:09:42 +0000 Subject: [PATCH] Added FSCTL_PIPE_LISTEN support. --- dlls/kernel/sync.c | 56 ++++++++-------------- dlls/ntdll/file.c | 87 ++++++++++++++++++++++++++++++---- include/wine/server_protocol.h | 4 +- server/named_pipe.c | 2 +- server/protocol.def | 2 +- server/trace.c | 2 +- 6 files changed, 103 insertions(+), 50 deletions(-) diff --git a/dlls/kernel/sync.c b/dlls/kernel/sync.c index fe785eca443..9a37727aea9 100644 --- a/dlls/kernel/sync.c +++ b/dlls/kernel/sync.c @@ -1310,50 +1310,34 @@ BOOL WINAPI WaitNamedPipeW (LPCWSTR name, DWORD nTimeOut) /*********************************************************************** * ConnectNamedPipe (KERNEL32.@) + * + * Connects to a named pipe + * + * Parameters + * hPipe: A handle to a named pipe returned by CreateNamedPipe + * overlapped: Optional OVERLAPPED struct + * + * Return values + * TRUE: Success + * FALSE: Failure, GetLastError can be called for further details */ BOOL WINAPI ConnectNamedPipe(HANDLE hPipe, LPOVERLAPPED overlapped) { - BOOL ret; - LPOVERLAPPED pov; - OVERLAPPED ov; + NTSTATUS status; + IO_STATUS_BLOCK status_block; TRACE("(%p,%p)\n", hPipe, overlapped); - if (!overlapped) - { - memset(&ov, 0, sizeof(ov)); - ov.hEvent = CreateEventW(NULL, 0, 0, NULL); - if (!ov.hEvent) return FALSE; - pov = &ov; - } - else pov = overlapped; - - pov->Internal = STATUS_PENDING; + if(overlapped) + overlapped->Internal = STATUS_PENDING; - SERVER_START_REQ( connect_named_pipe ) - { - req->handle = hPipe; - req->overlapped = pov; - req->func = PIPE_CompletionWait; - ret = !wine_server_call_err( req ); - } - SERVER_END_REQ; + status = NtFsControlFile(hPipe, overlapped ? overlapped->hEvent : NULL, NULL, NULL, + overlapped ? (IO_STATUS_BLOCK *)overlapped : &status_block, + FSCTL_PIPE_LISTEN, NULL, 0, NULL, 0); - if (ret) - { - if (overlapped) - { - SetLastError( ERROR_IO_PENDING ); - ret = FALSE; - } - else - { - ret = GetOverlappedResult(hPipe, &ov, NULL, TRUE); - CloseHandle(ov.hEvent); - } - } - - return ret; + if (status == STATUS_SUCCESS) return TRUE; + SetLastError( RtlNtStatusToDosError(status) ); + return FALSE; } /*********************************************************************** diff --git a/dlls/ntdll/file.c b/dlls/ntdll/file.c index 2e4d0427d52..cfd2c2111a9 100644 --- a/dlls/ntdll/file.c +++ b/dlls/ntdll/file.c @@ -862,24 +862,90 @@ NTSTATUS WINAPI NtDeviceIoControlFile(HANDLE DeviceHandle, HANDLE hEvent, return IoStatusBlock->u.Status; } -/****************************************************************************** - * NtFsControlFile [NTDLL.@] - * ZwFsControlFile [NTDLL.@] +/*********************************************************************** + * pipe_completion_wait (Internal) + */ +static void CALLBACK pipe_completion_wait(HANDLE event, PIO_STATUS_BLOCK iosb, ULONG status) +{ + TRACE("for %p/%p, status=%08lx\n", event, iosb, status); + + if (iosb) + iosb->u.Status = status; + NtSetEvent(event, NULL); + TRACE("done\n"); +} + +/************************************************************************** + * NtFsControlFile [NTDLL.@] + * ZwFsControlFile [NTDLL.@] + * + * Perform a file system control operation on an open file handle. + * + * PARAMS + * DeviceHandle [I] Handle returned from ZwOpenFile() or ZwCreateFile() + * Event [I] Event to signal upon completion (or NULL) + * ApcRoutine [I] Callback to call upon completion (or NULL) + * ApcContext [I] Context for ApcRoutine (or NULL) + * IoStatusBlock [O] Receives information about the operation on return + * FsControlCode [I] Control code for the operation to perform + * InputBuffer [I] Source for any input data required (or NULL) + * InputBufferSize [I] Size of InputBuffer + * OutputBuffer [O] Source for any output data returned (or NULL) + * OutputBufferSize [I] Size of OutputBuffer + * + * RETURNS + * Success: 0. IoStatusBlock is updated. + * Failure: An NTSTATUS error code describing the error. */ NTSTATUS WINAPI NtFsControlFile(HANDLE DeviceHandle, HANDLE Event OPTIONAL, PIO_APC_ROUTINE ApcRoutine, - PVOID ApcContext, PIO_STATUS_BLOCK IoStatusBlock, ULONG IoControlCode, + PVOID ApcContext, PIO_STATUS_BLOCK IoStatusBlock, ULONG FsControlCode, PVOID InputBuffer, ULONG InputBufferSize, PVOID OutputBuffer, ULONG OutputBufferSize) { NTSTATUS ret; TRACE("(%p,%p,%p,%p,%p,0x%08lx,%p,0x%08lx,%p,0x%08lx)\n", - DeviceHandle,Event,ApcRoutine,ApcContext,IoStatusBlock,IoControlCode, + DeviceHandle,Event,ApcRoutine,ApcContext,IoStatusBlock,FsControlCode, InputBuffer,InputBufferSize,OutputBuffer,OutputBufferSize); if(!IoStatusBlock) return STATUS_INVALID_PARAMETER; - switch(IoControlCode) + switch(FsControlCode) { + case FSCTL_PIPE_LISTEN : + { + HANDLE internal_event; + + if(!Event) + { + OBJECT_ATTRIBUTES obj; + InitializeObjectAttributes(&obj, NULL, 0, 0, NULL); + ret = NtCreateEvent(&internal_event, EVENT_ALL_ACCESS, &obj, FALSE, FALSE); + if(ret != STATUS_SUCCESS) return ret; + } + + SERVER_START_REQ(connect_named_pipe) + { + req->handle = DeviceHandle; + req->event = Event ? Event : internal_event; + req->func = pipe_completion_wait; + ret = wine_server_call(req); + } + SERVER_END_REQ; + + if(ret == STATUS_SUCCESS) + { + if(Event) + ret = STATUS_PENDING; + else + { + do + ret = NtWaitForSingleObject(internal_event, TRUE, NULL); + while(ret == STATUS_USER_APC); + NtClose(internal_event); + } + } + break; + } case FSCTL_PIPE_DISCONNECT : SERVER_START_REQ(disconnect_named_pipe) { @@ -888,11 +954,14 @@ NTSTATUS WINAPI NtFsControlFile(HANDLE DeviceHandle, HANDLE Event OPTIONAL, PIO_ if (!ret && reply->fd != -1) close(reply->fd); } SERVER_END_REQ; - return ret; + break; default : - FIXME("Unsupported IoControlCode %lx\n", IoControlCode); - return STATUS_NOT_SUPPORTED; + FIXME("Unsupported FsControlCode %lx\n", FsControlCode); + ret = STATUS_NOT_SUPPORTED; + break; } + IoStatusBlock->u.Status = ret; + return ret; } /****************************************************************************** diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h index e18d682a025..2f1ada8845d 100644 --- a/include/wine/server_protocol.h +++ b/include/wine/server_protocol.h @@ -2408,7 +2408,7 @@ struct connect_named_pipe_request { struct request_header __header; obj_handle_t handle; - void* overlapped; + obj_handle_t event; void* func; }; struct connect_named_pipe_reply @@ -4206,6 +4206,6 @@ union generic_reply struct set_mailslot_info_reply set_mailslot_info_reply; }; -#define SERVER_PROTOCOL_VERSION 191 +#define SERVER_PROTOCOL_VERSION 192 #endif /* __WINE_WINE_SERVER_PROTOCOL_H */ diff --git a/server/named_pipe.c b/server/named_pipe.c index b22dfb1524f..55a8ee08e18 100644 --- a/server/named_pipe.c +++ b/server/named_pipe.c @@ -671,7 +671,7 @@ DECL_HANDLER(connect_named_pipe) assert( !server->fd ); server->state = ps_wait_open; create_async( current, NULL, &server->wait_q, - req->func, req->overlapped, NULL ); + req->func, req->event, NULL ); async_terminate_queue( &server->pipe->waiters, STATUS_SUCCESS ); break; case ps_connected_server: diff --git a/server/protocol.def b/server/protocol.def index 422aa001e43..9e93f534695 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -1712,7 +1712,7 @@ enum message_type /* Connect to a named pipe */ @REQ(connect_named_pipe) obj_handle_t handle; - void* overlapped; + obj_handle_t event; void* func; @END diff --git a/server/trace.c b/server/trace.c index 538732fe747..2c00f2e5e03 100644 --- a/server/trace.c +++ b/server/trace.c @@ -2173,7 +2173,7 @@ static void dump_open_named_pipe_reply( const struct open_named_pipe_reply *req static void dump_connect_named_pipe_request( const struct connect_named_pipe_request *req ) { fprintf( stderr, " handle=%p,", req->handle ); - fprintf( stderr, " overlapped=%p,", req->overlapped ); + fprintf( stderr, " event=%p,", req->event ); fprintf( stderr, " func=%p", req->func ); }