From 134c83203a03c08f50701f97cd08f1ce7b2a6847 Mon Sep 17 00:00:00 2001 From: Jacek Caban Date: Tue, 21 Mar 2017 13:03:55 +0100 Subject: [PATCH] server: Added server-side FSCTL_PIPE_PEEK implementation. Signed-off-by: Jacek Caban Signed-off-by: Alexandre Julliard --- dlls/ntdll/file.c | 5 ++++ server/named_pipe.c | 62 ++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 66 insertions(+), 1 deletion(-) diff --git a/dlls/ntdll/file.c b/dlls/ntdll/file.c index c2678d5af90..c153e7bb5c5 100644 --- a/dlls/ntdll/file.c +++ b/dlls/ntdll/file.c @@ -1727,7 +1727,12 @@ NTSTATUS WINAPI NtFsControlFile(HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc } if ((status = server_get_unix_fd( handle, FILE_READ_DATA, &fd, &needs_close, NULL, NULL ))) + { + if (status == STATUS_BAD_DEVICE_TYPE) + status = server_ioctl_file( handle, event, apc, apc_context, io, code, + in_buffer, in_size, out_buffer, out_size ); break; + } #ifdef FIONREAD if (ioctl( fd, FIONREAD, &avail ) != 0) diff --git a/server/named_pipe.c b/server/named_pipe.c index adc27ca9c4b..85521e0953b 100644 --- a/server/named_pipe.c +++ b/server/named_pipe.c @@ -208,6 +208,8 @@ static int pipe_client_signaled( struct object *obj, struct wait_queue_entry *en static struct fd *pipe_client_get_fd( struct object *obj ); static void pipe_client_destroy( struct object *obj ); static obj_handle_t pipe_client_flush( struct fd *fd, struct async *async, int blocking ); +static obj_handle_t pipe_client_ioctl( struct fd *fd, ioctl_code_t code, struct async *async, + int blocking ); static enum server_fd_type pipe_client_get_fd_type( struct fd *fd ); static const struct object_ops pipe_client_ops = @@ -240,7 +242,7 @@ static const struct fd_ops pipe_client_fd_ops = no_fd_read, /* read */ pipe_end_write, /* write */ pipe_client_flush, /* flush */ - default_fd_ioctl, /* ioctl */ + pipe_client_ioctl, /* ioctl */ pipe_end_queue_async, /* queue_async */ pipe_end_reselect_async /* reselect_async */ }; @@ -792,6 +794,44 @@ static enum server_fd_type pipe_client_get_fd_type( struct fd *fd ) return FD_TYPE_PIPE; } +static void pipe_end_peek( struct pipe_end *pipe_end ) +{ + unsigned reply_size = get_reply_max_size(); + FILE_PIPE_PEEK_BUFFER *buffer; + struct pipe_message *message; + data_size_t avail = 0; + + if (!use_server_io( pipe_end )) + { + set_error( STATUS_NOT_SUPPORTED ); + return; + } + + if (reply_size < offsetof( FILE_PIPE_PEEK_BUFFER, Data )) + { + set_error( STATUS_INFO_LENGTH_MISMATCH ); + return; + } + reply_size -= offsetof( FILE_PIPE_PEEK_BUFFER, Data ); + + LIST_FOR_EACH_ENTRY( message, &pipe_end->message_queue, struct pipe_message, entry ) + avail += message->iosb->in_size - message->read_pos; + + if (avail) + { + message = LIST_ENTRY( list_head(&pipe_end->message_queue), struct pipe_message, entry ); + reply_size = min( reply_size, message->iosb->in_size - message->read_pos ); + } + else reply_size = 0; + + if (!(buffer = set_reply_data_size( offsetof( FILE_PIPE_PEEK_BUFFER, Data[reply_size] )))) return; + buffer->NamedPipeState = 0; /* FIXME */ + buffer->ReadDataAvailable = avail; + buffer->NumberOfMessages = 0; /* FIXME */ + buffer->MessageLength = 0; /* FIXME */ + if (reply_size) memcpy( buffer->Data, (const char *)message->iosb->in_data + message->read_pos, reply_size ); +} + static obj_handle_t pipe_server_ioctl( struct fd *fd, ioctl_code_t code, struct async *async, int blocking ) { @@ -858,6 +898,26 @@ static obj_handle_t pipe_server_ioctl( struct fd *fd, ioctl_code_t code, struct } return 0; + case FSCTL_PIPE_PEEK: + pipe_end_peek( &server->pipe_end ); + return 0; + + default: + return default_fd_ioctl( fd, code, async, blocking ); + } +} + +static obj_handle_t pipe_client_ioctl( struct fd *fd, ioctl_code_t code, struct async *async, + int blocking ) +{ + struct pipe_client *client = get_fd_user( fd ); + + switch(code) + { + case FSCTL_PIPE_PEEK: + pipe_end_peek( &client->pipe_end ); + return 0; + default: return default_fd_ioctl( fd, code, async, blocking ); }