diff --git a/dlls/ntdll/file.c b/dlls/ntdll/file.c index 2ae8bee94f5..92d9829ecec 100644 --- a/dlls/ntdll/file.c +++ b/dlls/ntdll/file.c @@ -2335,6 +2335,29 @@ NTSTATUS WINAPI NtSetInformationFile(HANDLE handle, PIO_STATUS_BLOCK io, else io->u.Status = STATUS_INVALID_PARAMETER_3; break; + case FilePipeInformation: + if (len >= sizeof(FILE_PIPE_INFORMATION)) + { + FILE_PIPE_INFORMATION *info = ptr; + + if ((info->CompletionMode | info->ReadMode) & ~1) + { + io->u.Status = STATUS_INVALID_PARAMETER; + break; + } + + SERVER_START_REQ( set_named_pipe_info ) + { + req->handle = wine_server_obj_handle( handle ); + req->flags = (info->CompletionMode ? NAMED_PIPE_NONBLOCKING_MODE : 0) | + (info->ReadMode ? NAMED_PIPE_MESSAGE_STREAM_READ : 0); + io->u.Status = wine_server_call( req ); + } + SERVER_END_REQ; + } + else io->u.Status = STATUS_INVALID_PARAMETER_3; + break; + case FileMailslotSetInformation: { FILE_MAILSLOT_SET_INFORMATION *info = ptr; diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h index 57ab8398571..cc966f299e4 100644 --- a/include/wine/server_protocol.h +++ b/include/wine/server_protocol.h @@ -3189,6 +3189,18 @@ struct get_named_pipe_info_reply }; +struct set_named_pipe_info_request +{ + struct request_header __header; + obj_handle_t handle; + unsigned int flags; + char __pad_20[4]; +}; +struct set_named_pipe_info_reply +{ + struct reply_header __header; +}; + struct create_window_request { @@ -5203,6 +5215,7 @@ enum request REQ_get_ioctl_result, REQ_create_named_pipe, REQ_get_named_pipe_info, + REQ_set_named_pipe_info, REQ_create_window, REQ_destroy_window, REQ_get_desktop_window, @@ -5464,6 +5477,7 @@ union generic_request struct get_ioctl_result_request get_ioctl_result_request; struct create_named_pipe_request create_named_pipe_request; struct get_named_pipe_info_request get_named_pipe_info_request; + struct set_named_pipe_info_request set_named_pipe_info_request; struct create_window_request create_window_request; struct destroy_window_request destroy_window_request; struct get_desktop_window_request get_desktop_window_request; @@ -5723,6 +5737,7 @@ union generic_reply struct get_ioctl_result_reply get_ioctl_result_reply; struct create_named_pipe_reply create_named_pipe_reply; struct get_named_pipe_info_reply get_named_pipe_info_reply; + struct set_named_pipe_info_reply set_named_pipe_info_reply; struct create_window_reply create_window_reply; struct destroy_window_reply destroy_window_reply; struct get_desktop_window_reply get_desktop_window_reply; @@ -5834,6 +5849,6 @@ union generic_reply struct set_suspend_context_reply set_suspend_context_reply; }; -#define SERVER_PROTOCOL_VERSION 456 +#define SERVER_PROTOCOL_VERSION 457 #endif /* __WINE_WINE_SERVER_PROTOCOL_H */ diff --git a/server/named_pipe.c b/server/named_pipe.c index d864478618a..3750d25e790 100644 --- a/server/named_pipe.c +++ b/server/named_pipe.c @@ -1046,3 +1046,41 @@ DECL_HANDLER(get_named_pipe_info) release_object(server); } } + +DECL_HANDLER(set_named_pipe_info) +{ + struct pipe_server *server; + struct pipe_client *client = NULL; + + server = get_pipe_server_obj( current->process, req->handle, FILE_WRITE_ATTRIBUTES ); + if (!server) + { + if (get_error() != STATUS_OBJECT_TYPE_MISMATCH) + return; + + clear_error(); + client = (struct pipe_client *)get_handle_obj( current->process, req->handle, + 0, &pipe_client_ops ); + if (!client) return; + server = client->server; + } + + if ((req->flags & ~(NAMED_PIPE_MESSAGE_STREAM_READ | NAMED_PIPE_NONBLOCKING_MODE)) || + ((req->flags & NAMED_PIPE_MESSAGE_STREAM_READ) && !(server->pipe->flags & NAMED_PIPE_MESSAGE_STREAM_WRITE))) + { + set_error( STATUS_INVALID_PARAMETER ); + } + else if (client) + { + client->pipe_flags = server->pipe->flags | req->flags; + } + else + { + server->pipe_flags = server->pipe->flags | req->flags; + } + + if (client) + release_object(client); + else + release_object(server); +} diff --git a/server/protocol.def b/server/protocol.def index a8c1fb95d81..c9270ea098e 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -2294,7 +2294,7 @@ enum message_type #define NAMED_PIPE_NONBLOCKING_MODE 0x0004 #define NAMED_PIPE_SERVER_END 0x8000 - +/* Get named pipe information by handle */ @REQ(get_named_pipe_info) obj_handle_t handle; @REPLY @@ -2306,6 +2306,11 @@ enum message_type unsigned int insize; @END +/* Set named pipe information by handle */ +@REQ(set_named_pipe_info) + obj_handle_t handle; + unsigned int flags; +@END /* Create a window */ @REQ(create_window) diff --git a/server/request.h b/server/request.h index e25e327d5f0..c75a6363bc9 100644 --- a/server/request.h +++ b/server/request.h @@ -251,6 +251,7 @@ DECL_HANDLER(ioctl); DECL_HANDLER(get_ioctl_result); DECL_HANDLER(create_named_pipe); DECL_HANDLER(get_named_pipe_info); +DECL_HANDLER(set_named_pipe_info); DECL_HANDLER(create_window); DECL_HANDLER(destroy_window); DECL_HANDLER(get_desktop_window); @@ -511,6 +512,7 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] = (req_handler)req_get_ioctl_result, (req_handler)req_create_named_pipe, (req_handler)req_get_named_pipe_info, + (req_handler)req_set_named_pipe_info, (req_handler)req_create_window, (req_handler)req_destroy_window, (req_handler)req_get_desktop_window, @@ -1536,6 +1538,9 @@ C_ASSERT( FIELD_OFFSET(struct get_named_pipe_info_reply, instances) == 20 ); C_ASSERT( FIELD_OFFSET(struct get_named_pipe_info_reply, outsize) == 24 ); C_ASSERT( FIELD_OFFSET(struct get_named_pipe_info_reply, insize) == 28 ); C_ASSERT( sizeof(struct get_named_pipe_info_reply) == 32 ); +C_ASSERT( FIELD_OFFSET(struct set_named_pipe_info_request, handle) == 12 ); +C_ASSERT( FIELD_OFFSET(struct set_named_pipe_info_request, flags) == 16 ); +C_ASSERT( sizeof(struct set_named_pipe_info_request) == 24 ); C_ASSERT( FIELD_OFFSET(struct create_window_request, parent) == 12 ); C_ASSERT( FIELD_OFFSET(struct create_window_request, owner) == 16 ); C_ASSERT( FIELD_OFFSET(struct create_window_request, atom) == 20 ); diff --git a/server/trace.c b/server/trace.c index 483435413f6..cb8da0c365f 100644 --- a/server/trace.c +++ b/server/trace.c @@ -2776,6 +2776,12 @@ static void dump_get_named_pipe_info_reply( const struct get_named_pipe_info_rep fprintf( stderr, ", insize=%08x", req->insize ); } +static void dump_set_named_pipe_info_request( const struct set_named_pipe_info_request *req ) +{ + fprintf( stderr, " handle=%04x", req->handle ); + fprintf( stderr, ", flags=%08x", req->flags ); +} + static void dump_create_window_request( const struct create_window_request *req ) { fprintf( stderr, " parent=%08x", req->parent ); @@ -4226,6 +4232,7 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = { (dump_func)dump_get_ioctl_result_request, (dump_func)dump_create_named_pipe_request, (dump_func)dump_get_named_pipe_info_request, + (dump_func)dump_set_named_pipe_info_request, (dump_func)dump_create_window_request, (dump_func)dump_destroy_window_request, (dump_func)dump_get_desktop_window_request, @@ -4483,6 +4490,7 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = { (dump_func)dump_get_ioctl_result_reply, (dump_func)dump_create_named_pipe_reply, (dump_func)dump_get_named_pipe_info_reply, + NULL, (dump_func)dump_create_window_reply, NULL, (dump_func)dump_get_desktop_window_reply, @@ -4740,6 +4748,7 @@ static const char * const req_names[REQ_NB_REQUESTS] = { "get_ioctl_result", "create_named_pipe", "get_named_pipe_info", + "set_named_pipe_info", "create_window", "destroy_window", "get_desktop_window",