blob: a736d83e45355be2e0de4b5c839c81ad8a8ac46e [file] [log] [blame]
Mike McCormackde7c3002001-07-10 19:16:49 +00001/*
2 * Server-side pipe management
3 *
4 * Copyright (C) 1998 Alexandre Julliard
Mike McCormackbf554572001-08-23 23:29:20 +00005 * Copyright (C) 2001 Mike McCormack
6 *
Alexandre Julliard0799c1a2002-03-09 23:29:33 +00007 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
Jonathan Ernst360a3f92006-05-18 14:49:52 +020019 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
Alexandre Julliard0799c1a2002-03-09 23:29:33 +000020 *
Mike McCormackbf554572001-08-23 23:29:20 +000021 * TODO:
Mike McCormackef8b9462003-05-15 04:22:45 +000022 * message mode
Mike McCormackde7c3002001-07-10 19:16:49 +000023 */
24
25#include "config.h"
Alexandre Julliard5769d1d2002-04-26 19:05:15 +000026#include "wine/port.h"
Mike McCormackde7c3002001-07-10 19:16:49 +000027
28#include <assert.h>
29#include <fcntl.h>
30#include <string.h>
Alexandre Julliarde37c6e12003-09-05 23:08:26 +000031#include <stdarg.h>
Mike McCormackde7c3002001-07-10 19:16:49 +000032#include <stdio.h>
33#include <stdlib.h>
34#include <sys/time.h>
35#include <sys/types.h>
Steven Edwards037c8a12003-02-11 22:27:13 +000036#ifdef HAVE_SYS_SOCKET_H
Mike McCormackde7c3002001-07-10 19:16:49 +000037#include <sys/socket.h>
Steven Edwards037c8a12003-02-11 22:27:13 +000038#endif
Mike McCormackde7c3002001-07-10 19:16:49 +000039#include <time.h>
40#include <unistd.h>
Steven Edwards57279182005-03-04 12:38:36 +000041#ifdef HAVE_POLL_H
42#include <poll.h>
43#endif
Mike McCormackde7c3002001-07-10 19:16:49 +000044
Ge van Geldorp1a1583a2005-11-28 17:32:54 +010045#include "ntstatus.h"
46#define WIN32_NO_STATUS
Alexandre Julliarde37c6e12003-09-05 23:08:26 +000047#include "windef.h"
Robert Shearmane51dd362005-06-08 19:11:46 +000048#include "winternl.h"
Mike McCormackde7c3002001-07-10 19:16:49 +000049
Alexandre Julliard863637b2003-01-30 00:26:44 +000050#include "file.h"
Mike McCormackde7c3002001-07-10 19:16:49 +000051#include "handle.h"
52#include "thread.h"
53#include "request.h"
54
Mike McCormackbf554572001-08-23 23:29:20 +000055enum pipe_state
56{
Mike McCormackbf554572001-08-23 23:29:20 +000057 ps_idle_server,
58 ps_wait_open,
Mike McCormackbf554572001-08-23 23:29:20 +000059 ps_connected_server,
Mike McCormackef8b9462003-05-15 04:22:45 +000060 ps_wait_disconnect,
61 ps_disconnected_server,
62 ps_wait_connect
63};
64
Mike McCormackde7c3002001-07-10 19:16:49 +000065struct named_pipe;
66
Mike McCormackef8b9462003-05-15 04:22:45 +000067struct pipe_server
Mike McCormackde7c3002001-07-10 19:16:49 +000068{
Alexandre Julliard7c1cf8f2005-02-03 10:48:23 +000069 struct object obj; /* object header */
70 struct fd *fd; /* pipe file descriptor */
71 struct list entry; /* entry in named pipe servers list */
72 enum pipe_state state; /* server state */
73 struct pipe_client *client; /* client that this server is connected to */
Mike McCormackef8b9462003-05-15 04:22:45 +000074 struct named_pipe *pipe;
Mike McCormackef8b9462003-05-15 04:22:45 +000075 struct timeout_user *flush_poll;
76 struct event *event;
Alexandre Julliarddf09ac52007-04-02 20:09:29 +020077 struct async_queue *wait_q; /* only a single one can be queued */
Robert Shearmane51dd362005-06-08 19:11:46 +000078 unsigned int options; /* pipe options */
Mike McCormackef8b9462003-05-15 04:22:45 +000079};
80
81struct pipe_client
82{
Alexandre Julliard7c1cf8f2005-02-03 10:48:23 +000083 struct object obj; /* object header */
84 struct fd *fd; /* pipe file descriptor */
85 struct pipe_server *server; /* server that this client is connected to */
Robert Shearmane51dd362005-06-08 19:11:46 +000086 unsigned int flags; /* file flags */
Mike McCormackde7c3002001-07-10 19:16:49 +000087};
88
89struct named_pipe
90{
91 struct object obj; /* object header */
Eric Pouech5a2591d2005-04-18 14:57:04 +000092 unsigned int flags;
Mike McCormackde7c3002001-07-10 19:16:49 +000093 unsigned int maxinstances;
94 unsigned int outsize;
95 unsigned int insize;
96 unsigned int timeout;
Mike McCormackef8b9462003-05-15 04:22:45 +000097 unsigned int instances;
Alexandre Julliard7c1cf8f2005-02-03 10:48:23 +000098 struct list servers; /* list of servers using this pipe */
Alexandre Julliarddf09ac52007-04-02 20:09:29 +020099 struct async_queue *waiters; /* list of clients waiting to connect */
Mike McCormackde7c3002001-07-10 19:16:49 +0000100};
101
Vitaliy Margolenbabfa792005-12-05 13:09:35 +0100102struct named_pipe_device
103{
104 struct object obj; /* object header */
Alexandre Julliard26e60d82005-12-12 14:30:06 +0100105 struct fd *fd; /* pseudo-fd for ioctls */
Vitaliy Margolenbabfa792005-12-05 13:09:35 +0100106 struct namespace *pipes; /* named pipe namespace */
107};
108
Mike McCormackde7c3002001-07-10 19:16:49 +0000109static void named_pipe_dump( struct object *obj, int verbose );
Alexandre Julliarda510a7e2005-12-12 16:46:17 +0100110static unsigned int named_pipe_map_access( struct object *obj, unsigned int access );
Alexandre Julliardde1866d2007-03-22 16:47:46 +0100111static struct object *named_pipe_open_file( struct object *obj, unsigned int access,
112 unsigned int sharing, unsigned int options );
Mike McCormackef8b9462003-05-15 04:22:45 +0000113static void named_pipe_destroy( struct object *obj );
Mike McCormackde7c3002001-07-10 19:16:49 +0000114
115static const struct object_ops named_pipe_ops =
116{
117 sizeof(struct named_pipe), /* size */
118 named_pipe_dump, /* dump */
119 no_add_queue, /* add_queue */
120 NULL, /* remove_queue */
121 NULL, /* signaled */
122 NULL, /* satisfied */
Mike McCormackf92fff62005-04-24 17:35:52 +0000123 no_signal, /* signal */
Mike McCormackde7c3002001-07-10 19:16:49 +0000124 no_get_fd, /* get_fd */
Alexandre Julliarda510a7e2005-12-12 16:46:17 +0100125 named_pipe_map_access, /* map_access */
Vitaliy Margolenbaffcb92005-11-22 14:55:42 +0000126 no_lookup_name, /* lookup_name */
Alexandre Julliardde1866d2007-03-22 16:47:46 +0100127 named_pipe_open_file, /* open_file */
Alexandre Julliardb9b1ea92005-06-09 15:39:52 +0000128 no_close_handle, /* close_handle */
Mike McCormackde7c3002001-07-10 19:16:49 +0000129 named_pipe_destroy /* destroy */
130};
131
Alexandre Julliarda510a7e2005-12-12 16:46:17 +0100132/* functions common to server and client */
133static unsigned int pipe_map_access( struct object *obj, unsigned int access );
134
Mike McCormackef8b9462003-05-15 04:22:45 +0000135/* server end functions */
136static void pipe_server_dump( struct object *obj, int verbose );
137static struct fd *pipe_server_get_fd( struct object *obj );
138static void pipe_server_destroy( struct object *obj);
Alexandre Julliarddf651872007-03-27 16:51:44 +0200139static void pipe_server_flush( struct fd *fd, struct event **event );
Alexandre Julliard89304272006-11-20 14:14:04 +0100140static enum server_fd_type pipe_server_get_info( struct fd *fd, int *flags );
Mike McCormackde7c3002001-07-10 19:16:49 +0000141
Mike McCormackef8b9462003-05-15 04:22:45 +0000142static const struct object_ops pipe_server_ops =
Mike McCormackde7c3002001-07-10 19:16:49 +0000143{
Mike McCormackef8b9462003-05-15 04:22:45 +0000144 sizeof(struct pipe_server), /* size */
145 pipe_server_dump, /* dump */
Alexandre Julliardba896e72007-04-04 19:39:29 +0200146 add_queue, /* add_queue */
147 remove_queue, /* remove_queue */
Alexandre Julliard863637b2003-01-30 00:26:44 +0000148 default_fd_signaled, /* signaled */
Mike McCormackde7c3002001-07-10 19:16:49 +0000149 no_satisfied, /* satisfied */
Mike McCormackf92fff62005-04-24 17:35:52 +0000150 no_signal, /* signal */
Mike McCormackef8b9462003-05-15 04:22:45 +0000151 pipe_server_get_fd, /* get_fd */
Alexandre Julliarda510a7e2005-12-12 16:46:17 +0100152 pipe_map_access, /* map_access */
Vitaliy Margolenbaffcb92005-11-22 14:55:42 +0000153 no_lookup_name, /* lookup_name */
Alexandre Julliard7e71c1d2007-03-22 11:44:29 +0100154 no_open_file, /* open_file */
Alexandre Julliard715d78e2006-11-02 20:52:22 +0100155 fd_close_handle, /* close_handle */
Mike McCormackef8b9462003-05-15 04:22:45 +0000156 pipe_server_destroy /* destroy */
Alexandre Julliard863637b2003-01-30 00:26:44 +0000157};
158
Mike McCormackef8b9462003-05-15 04:22:45 +0000159static const struct fd_ops pipe_server_fd_ops =
Alexandre Julliard863637b2003-01-30 00:26:44 +0000160{
Robert Shearmane51dd362005-06-08 19:11:46 +0000161 default_fd_get_poll_events, /* get_poll_events */
Mike McCormackde7c3002001-07-10 19:16:49 +0000162 default_poll_event, /* poll_event */
Mike McCormackef8b9462003-05-15 04:22:45 +0000163 pipe_server_flush, /* flush */
Robert Shearmane51dd362005-06-08 19:11:46 +0000164 pipe_server_get_info, /* get_file_info */
165 default_fd_queue_async, /* queue_async */
166 default_fd_cancel_async, /* cancel_async */
Mike McCormackef8b9462003-05-15 04:22:45 +0000167};
168
169/* client end functions */
170static void pipe_client_dump( struct object *obj, int verbose );
171static struct fd *pipe_client_get_fd( struct object *obj );
172static void pipe_client_destroy( struct object *obj );
Alexandre Julliarddf651872007-03-27 16:51:44 +0200173static void pipe_client_flush( struct fd *fd, struct event **event );
Alexandre Julliard89304272006-11-20 14:14:04 +0100174static enum server_fd_type pipe_client_get_info( struct fd *fd, int *flags );
Mike McCormackef8b9462003-05-15 04:22:45 +0000175
176static const struct object_ops pipe_client_ops =
177{
178 sizeof(struct pipe_client), /* size */
179 pipe_client_dump, /* dump */
Alexandre Julliardba896e72007-04-04 19:39:29 +0200180 add_queue, /* add_queue */
181 remove_queue, /* remove_queue */
Mike McCormackef8b9462003-05-15 04:22:45 +0000182 default_fd_signaled, /* signaled */
183 no_satisfied, /* satisfied */
Mike McCormackf92fff62005-04-24 17:35:52 +0000184 no_signal, /* signal */
Mike McCormackef8b9462003-05-15 04:22:45 +0000185 pipe_client_get_fd, /* get_fd */
Alexandre Julliarda510a7e2005-12-12 16:46:17 +0100186 pipe_map_access, /* map_access */
Vitaliy Margolenbaffcb92005-11-22 14:55:42 +0000187 no_lookup_name, /* lookup_name */
Alexandre Julliard7e71c1d2007-03-22 11:44:29 +0100188 no_open_file, /* open_file */
Alexandre Julliard715d78e2006-11-02 20:52:22 +0100189 fd_close_handle, /* close_handle */
Mike McCormackef8b9462003-05-15 04:22:45 +0000190 pipe_client_destroy /* destroy */
191};
192
193static const struct fd_ops pipe_client_fd_ops =
194{
Robert Shearmane51dd362005-06-08 19:11:46 +0000195 default_fd_get_poll_events, /* get_poll_events */
Mike McCormackef8b9462003-05-15 04:22:45 +0000196 default_poll_event, /* poll_event */
197 pipe_client_flush, /* flush */
Robert Shearmane51dd362005-06-08 19:11:46 +0000198 pipe_client_get_info, /* get_file_info */
199 default_fd_queue_async, /* queue_async */
200 default_fd_cancel_async /* cancel_async */
Mike McCormackde7c3002001-07-10 19:16:49 +0000201};
202
Vitaliy Margolenbabfa792005-12-05 13:09:35 +0100203static void named_pipe_device_dump( struct object *obj, int verbose );
Alexandre Julliard26e60d82005-12-12 14:30:06 +0100204static struct fd *named_pipe_device_get_fd( struct object *obj );
Vitaliy Margolenbabfa792005-12-05 13:09:35 +0100205static struct object *named_pipe_device_lookup_name( struct object *obj,
206 struct unicode_str *name, unsigned int attr );
Alexandre Julliard94655c82007-03-22 11:52:40 +0100207static struct object *named_pipe_device_open_file( struct object *obj, unsigned int access,
208 unsigned int sharing, unsigned int options );
Vitaliy Margolenbabfa792005-12-05 13:09:35 +0100209static void named_pipe_device_destroy( struct object *obj );
Alexandre Julliard89304272006-11-20 14:14:04 +0100210static enum server_fd_type named_pipe_device_get_file_info( struct fd *fd, int *flags );
Vitaliy Margolenbabfa792005-12-05 13:09:35 +0100211
212static const struct object_ops named_pipe_device_ops =
213{
214 sizeof(struct named_pipe_device), /* size */
215 named_pipe_device_dump, /* dump */
216 no_add_queue, /* add_queue */
217 NULL, /* remove_queue */
218 NULL, /* signaled */
219 no_satisfied, /* satisfied */
220 no_signal, /* signal */
Alexandre Julliard26e60d82005-12-12 14:30:06 +0100221 named_pipe_device_get_fd, /* get_fd */
Alexandre Julliarda510a7e2005-12-12 16:46:17 +0100222 pipe_map_access, /* map_access */
Vitaliy Margolenbabfa792005-12-05 13:09:35 +0100223 named_pipe_device_lookup_name, /* lookup_name */
Alexandre Julliard94655c82007-03-22 11:52:40 +0100224 named_pipe_device_open_file, /* open_file */
Alexandre Julliard715d78e2006-11-02 20:52:22 +0100225 fd_close_handle, /* close_handle */
Vitaliy Margolenbabfa792005-12-05 13:09:35 +0100226 named_pipe_device_destroy /* destroy */
227};
228
Alexandre Julliard26e60d82005-12-12 14:30:06 +0100229static const struct fd_ops named_pipe_device_fd_ops =
230{
Alexandre Julliard1acb9302005-12-13 12:00:11 +0100231 default_fd_get_poll_events, /* get_poll_events */
232 default_poll_event, /* poll_event */
233 no_flush, /* flush */
234 named_pipe_device_get_file_info, /* get_file_info */
235 default_fd_queue_async, /* queue_async */
236 default_fd_cancel_async /* cancel_async */
Alexandre Julliard26e60d82005-12-12 14:30:06 +0100237};
238
Mike McCormackde7c3002001-07-10 19:16:49 +0000239static void named_pipe_dump( struct object *obj, int verbose )
240{
Mike McCormackef8b9462003-05-15 04:22:45 +0000241 struct named_pipe *pipe = (struct named_pipe *) obj;
Mike McCormackde7c3002001-07-10 19:16:49 +0000242 assert( obj->ops == &named_pipe_ops );
Alexandre Julliard7c1cf8f2005-02-03 10:48:23 +0000243 fprintf( stderr, "Named pipe " );
244 dump_object_name( &pipe->obj );
245 fprintf( stderr, "\n" );
Mike McCormackde7c3002001-07-10 19:16:49 +0000246}
247
Alexandre Julliarda510a7e2005-12-12 16:46:17 +0100248static unsigned int named_pipe_map_access( struct object *obj, unsigned int access )
249{
250 if (access & GENERIC_READ) access |= STANDARD_RIGHTS_READ;
251 if (access & GENERIC_WRITE) access |= STANDARD_RIGHTS_WRITE | FILE_CREATE_PIPE_INSTANCE;
252 if (access & GENERIC_EXECUTE) access |= STANDARD_RIGHTS_EXECUTE;
253 if (access & GENERIC_ALL) access |= STANDARD_RIGHTS_ALL;
254 return access & ~(GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE | GENERIC_ALL);
255}
256
Mike McCormackef8b9462003-05-15 04:22:45 +0000257static void pipe_server_dump( struct object *obj, int verbose )
Mike McCormackde7c3002001-07-10 19:16:49 +0000258{
Mike McCormackef8b9462003-05-15 04:22:45 +0000259 struct pipe_server *server = (struct pipe_server *) obj;
260 assert( obj->ops == &pipe_server_ops );
Alexandre Julliard7c1cf8f2005-02-03 10:48:23 +0000261 fprintf( stderr, "Named pipe server pipe=%p state=%d\n", server->pipe, server->state );
Mike McCormackef8b9462003-05-15 04:22:45 +0000262}
263
264static void pipe_client_dump( struct object *obj, int verbose )
265{
266 struct pipe_client *client = (struct pipe_client *) obj;
Alexandre Julliard7c1cf8f2005-02-03 10:48:23 +0000267 assert( obj->ops == &pipe_client_ops );
268 fprintf( stderr, "Named pipe client server=%p\n", client->server );
Mike McCormackde7c3002001-07-10 19:16:49 +0000269}
270
Alexandre Julliard7c1cf8f2005-02-03 10:48:23 +0000271static void named_pipe_destroy( struct object *obj)
272{
273 struct named_pipe *pipe = (struct named_pipe *) obj;
274
275 assert( list_empty( &pipe->servers ) );
276 assert( !pipe->instances );
Alexandre Julliardb2cba952007-04-03 19:36:07 +0200277 free_async_queue( pipe->waiters );
Mike McCormackef8b9462003-05-15 04:22:45 +0000278}
279
280static struct fd *pipe_client_get_fd( struct object *obj )
281{
282 struct pipe_client *client = (struct pipe_client *) obj;
Robert Shearman37957092005-06-10 19:54:46 +0000283 if (client->fd)
Mike McCormackef8b9462003-05-15 04:22:45 +0000284 return (struct fd *) grab_object( client->fd );
Bill Medland3f7c3ff2003-04-17 02:14:04 +0000285 set_error( STATUS_PIPE_DISCONNECTED );
286 return NULL;
Alexandre Julliarde66207e2003-02-19 00:33:32 +0000287}
288
Mike McCormackef8b9462003-05-15 04:22:45 +0000289static struct fd *pipe_server_get_fd( struct object *obj )
Mike McCormackde7c3002001-07-10 19:16:49 +0000290{
Mike McCormackef8b9462003-05-15 04:22:45 +0000291 struct pipe_server *server = (struct pipe_server *) obj;
Mike McCormackde7c3002001-07-10 19:16:49 +0000292
Mike McCormackef8b9462003-05-15 04:22:45 +0000293 switch(server->state)
Mike McCormackbf554572001-08-23 23:29:20 +0000294 {
Mike McCormackef8b9462003-05-15 04:22:45 +0000295 case ps_connected_server:
296 case ps_wait_disconnect:
297 assert( server->fd );
298 return (struct fd *) grab_object( server->fd );
Mike McCormackde7c3002001-07-10 19:16:49 +0000299
Mike McCormackef8b9462003-05-15 04:22:45 +0000300 case ps_wait_open:
301 case ps_idle_server:
302 set_error( STATUS_PIPE_LISTENING );
303 break;
304
305 case ps_disconnected_server:
306 case ps_wait_connect:
307 set_error( STATUS_PIPE_DISCONNECTED );
308 break;
Mike McCormackef8b9462003-05-15 04:22:45 +0000309 }
310 return NULL;
Alexandre Julliarde66207e2003-02-19 00:33:32 +0000311}
312
Mike McCormackef8b9462003-05-15 04:22:45 +0000313
314static void notify_empty( struct pipe_server *server )
315{
Robert Shearman37957092005-06-10 19:54:46 +0000316 if (!server->flush_poll)
Mike McCormackef8b9462003-05-15 04:22:45 +0000317 return;
318 assert( server->state == ps_connected_server );
319 assert( server->event );
320 remove_timeout_user( server->flush_poll );
321 server->flush_poll = NULL;
322 set_event( server->event );
323 release_object( server->event );
324 server->event = NULL;
325}
326
327static void do_disconnect( struct pipe_server *server )
328{
329 /* we may only have a server fd, if the client disconnected */
Robert Shearman37957092005-06-10 19:54:46 +0000330 if (server->client)
Mike McCormackef8b9462003-05-15 04:22:45 +0000331 {
332 assert( server->client->server == server );
333 assert( server->client->fd );
334 release_object( server->client->fd );
335 server->client->fd = NULL;
336 }
337 assert( server->fd );
338 release_object( server->fd );
339 server->fd = NULL;
340}
341
Alexandre Julliarda510a7e2005-12-12 16:46:17 +0100342static unsigned int pipe_map_access( struct object *obj, unsigned int access )
343{
344 if (access & GENERIC_READ) access |= FILE_GENERIC_READ;
345 if (access & GENERIC_WRITE) access |= FILE_GENERIC_WRITE;
346 if (access & GENERIC_EXECUTE) access |= FILE_GENERIC_EXECUTE;
347 if (access & GENERIC_ALL) access |= FILE_ALL_ACCESS;
348 return access & ~(GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE | GENERIC_ALL);
349}
350
Mike McCormackef8b9462003-05-15 04:22:45 +0000351static void pipe_server_destroy( struct object *obj)
352{
353 struct pipe_server *server = (struct pipe_server *)obj;
354
355 assert( obj->ops == &pipe_server_ops );
356
Robert Shearman37957092005-06-10 19:54:46 +0000357 if (server->fd)
Mike McCormackef8b9462003-05-15 04:22:45 +0000358 {
359 notify_empty( server );
360 do_disconnect( server );
361 }
362
Robert Shearman37957092005-06-10 19:54:46 +0000363 if (server->client)
Mike McCormackef8b9462003-05-15 04:22:45 +0000364 {
365 server->client->server = NULL;
366 server->client = NULL;
367 }
368
Alexandre Julliardb2cba952007-04-03 19:36:07 +0200369 free_async_queue( server->wait_q );
Mike McCormackef8b9462003-05-15 04:22:45 +0000370
371 assert( server->pipe->instances );
372 server->pipe->instances--;
373
Alexandre Julliard7c1cf8f2005-02-03 10:48:23 +0000374 list_remove( &server->entry );
Mike McCormackef8b9462003-05-15 04:22:45 +0000375 release_object( server->pipe );
376}
377
378static void pipe_client_destroy( struct object *obj)
379{
380 struct pipe_client *client = (struct pipe_client *)obj;
381 struct pipe_server *server = client->server;
382
383 assert( obj->ops == &pipe_client_ops );
384
Robert Shearman37957092005-06-10 19:54:46 +0000385 if (server)
Mike McCormackef8b9462003-05-15 04:22:45 +0000386 {
387 notify_empty( server );
388
Robert Shearman37957092005-06-10 19:54:46 +0000389 switch(server->state)
Mike McCormackef8b9462003-05-15 04:22:45 +0000390 {
391 case ps_connected_server:
392 /* Don't destroy the server's fd here as we can't
393 do a successful flush without it. */
394 server->state = ps_wait_disconnect;
395 release_object( client->fd );
396 client->fd = NULL;
397 break;
398 case ps_disconnected_server:
399 server->state = ps_wait_connect;
400 break;
Alexandre Julliard7c1cf8f2005-02-03 10:48:23 +0000401 case ps_idle_server:
402 case ps_wait_open:
403 case ps_wait_disconnect:
404 case ps_wait_connect:
Mike McCormackef8b9462003-05-15 04:22:45 +0000405 assert( 0 );
406 }
407 assert( server->client );
408 server->client = NULL;
409 client->server = NULL;
410 }
411 assert( !client->fd );
412}
413
Vitaliy Margolenbabfa792005-12-05 13:09:35 +0100414static void named_pipe_device_dump( struct object *obj, int verbose )
415{
416 assert( obj->ops == &named_pipe_device_ops );
417 fprintf( stderr, "Named pipe device\n" );
418}
419
Alexandre Julliard26e60d82005-12-12 14:30:06 +0100420static struct fd *named_pipe_device_get_fd( struct object *obj )
421{
422 struct named_pipe_device *device = (struct named_pipe_device *)obj;
Alexandre Julliard5bcd0882005-12-13 11:22:28 +0100423 return (struct fd *)grab_object( device->fd );
Alexandre Julliard26e60d82005-12-12 14:30:06 +0100424}
425
Vitaliy Margolenbabfa792005-12-05 13:09:35 +0100426static struct object *named_pipe_device_lookup_name( struct object *obj, struct unicode_str *name,
427 unsigned int attr )
428{
429 struct named_pipe_device *device = (struct named_pipe_device*)obj;
430 struct object *found;
431
432 assert( obj->ops == &named_pipe_device_ops );
433 assert( device->pipes );
434
Vitaliy Margolenbabfa792005-12-05 13:09:35 +0100435 if ((found = find_object( device->pipes, name, attr | OBJ_CASE_INSENSITIVE )))
436 name->len = 0;
437
438 return found;
439}
440
Alexandre Julliard94655c82007-03-22 11:52:40 +0100441static struct object *named_pipe_device_open_file( struct object *obj, unsigned int access,
442 unsigned int sharing, unsigned int options )
443{
444 return grab_object( obj );
445}
446
Vitaliy Margolenbabfa792005-12-05 13:09:35 +0100447static void named_pipe_device_destroy( struct object *obj )
448{
449 struct named_pipe_device *device = (struct named_pipe_device*)obj;
450 assert( obj->ops == &named_pipe_device_ops );
Alexandre Julliard26e60d82005-12-12 14:30:06 +0100451 if (device->fd) release_object( device->fd );
Michael Stefaniuc5ceccec2006-10-09 23:34:36 +0200452 free( device->pipes );
Vitaliy Margolenbabfa792005-12-05 13:09:35 +0100453}
454
Alexandre Julliard89304272006-11-20 14:14:04 +0100455static enum server_fd_type named_pipe_device_get_file_info( struct fd *fd, int *flags )
Alexandre Julliard1acb9302005-12-13 12:00:11 +0100456{
Alexandre Julliard89304272006-11-20 14:14:04 +0100457 *flags = 0;
458 return FD_TYPE_DEVICE;
Alexandre Julliard1acb9302005-12-13 12:00:11 +0100459}
460
Alexandre Julliardb00fb172006-03-22 20:32:04 +0100461void create_named_pipe_device( struct directory *root, const struct unicode_str *name )
Vitaliy Margolenbabfa792005-12-05 13:09:35 +0100462{
Vitaliy Margolenbabfa792005-12-05 13:09:35 +0100463 struct named_pipe_device *dev;
464
Alexandre Julliardd13095b2005-12-05 14:52:02 +0100465 if ((dev = create_named_object_dir( root, name, 0, &named_pipe_device_ops )) &&
Vitaliy Margolenbabfa792005-12-05 13:09:35 +0100466 get_error() != STATUS_OBJECT_NAME_EXISTS)
467 {
Alexandre Julliard26e60d82005-12-12 14:30:06 +0100468 dev->pipes = NULL;
469 if (!(dev->fd = alloc_pseudo_fd( &named_pipe_device_fd_ops, &dev->obj )) ||
470 !(dev->pipes = create_namespace( 7 )))
Vitaliy Margolenbabfa792005-12-05 13:09:35 +0100471 {
472 release_object( dev );
473 dev = NULL;
474 }
475 }
Alexandre Julliardb00fb172006-03-22 20:32:04 +0100476 if (dev) make_object_static( &dev->obj );
Vitaliy Margolenbabfa792005-12-05 13:09:35 +0100477}
478
Mike McCormackef8b9462003-05-15 04:22:45 +0000479static int pipe_data_remaining( struct pipe_server *server )
480{
481 struct pollfd pfd;
482 int fd;
483
484 assert( server->client );
485
486 fd = get_unix_fd( server->client->fd );
Robert Shearman37957092005-06-10 19:54:46 +0000487 if (fd < 0)
Mike McCormackef8b9462003-05-15 04:22:45 +0000488 return 0;
489 pfd.fd = fd;
490 pfd.events = POLLIN;
491 pfd.revents = 0;
492
Robert Shearman37957092005-06-10 19:54:46 +0000493 if (0 > poll( &pfd, 1, 0 ))
Mike McCormackef8b9462003-05-15 04:22:45 +0000494 return 0;
495
496 return pfd.revents&POLLIN;
497}
498
499static void check_flushed( void *arg )
500{
501 struct pipe_server *server = (struct pipe_server*) arg;
502
503 assert( server->event );
Robert Shearman37957092005-06-10 19:54:46 +0000504 if (pipe_data_remaining( server ))
Mike McCormackef8b9462003-05-15 04:22:45 +0000505 {
Alexandre Julliard753c8702006-08-10 16:42:09 +0200506 struct timeval tv = current_time;
Mike McCormackef8b9462003-05-15 04:22:45 +0000507 add_timeout( &tv, 100 );
508 server->flush_poll = add_timeout_user( &tv, check_flushed, server );
509 }
510 else
Mike McCormack99a6efa2004-07-15 18:59:58 +0000511 {
512 /* notify_empty( server ); */
513 server->flush_poll = NULL;
514 set_event( server->event );
515 release_object( server->event );
516 server->event = NULL;
517 }
Mike McCormackef8b9462003-05-15 04:22:45 +0000518}
519
Alexandre Julliarddf651872007-03-27 16:51:44 +0200520static void pipe_server_flush( struct fd *fd, struct event **event )
Mike McCormackef8b9462003-05-15 04:22:45 +0000521{
522 struct pipe_server *server = get_fd_user( fd );
523
Alexandre Julliarddf651872007-03-27 16:51:44 +0200524 if (!server || server->state != ps_connected_server) return;
Mike McCormackef8b9462003-05-15 04:22:45 +0000525
526 /* FIXME: if multiple threads flush the same pipe,
527 maybe should create a list of processes to notify */
Alexandre Julliarddf651872007-03-27 16:51:44 +0200528 if (server->flush_poll) return;
Mike McCormackef8b9462003-05-15 04:22:45 +0000529
Robert Shearman37957092005-06-10 19:54:46 +0000530 if (pipe_data_remaining( server ))
Mike McCormackef8b9462003-05-15 04:22:45 +0000531 {
Alexandre Julliard753c8702006-08-10 16:42:09 +0200532 struct timeval tv = current_time;
Mike McCormackef8b9462003-05-15 04:22:45 +0000533
534 /* this kind of sux -
535 there's no unix way to be alerted when a pipe becomes empty */
Vitaliy Margolenf676bc82005-12-02 15:55:48 +0100536 server->event = create_event( NULL, NULL, 0, 0, 0 );
Alexandre Julliarddf651872007-03-27 16:51:44 +0200537 if (!server->event) return;
Mike McCormackef8b9462003-05-15 04:22:45 +0000538 add_timeout( &tv, 100 );
539 server->flush_poll = add_timeout_user( &tv, check_flushed, server );
540 *event = server->event;
541 }
Mike McCormackef8b9462003-05-15 04:22:45 +0000542}
543
Alexandre Julliarddf651872007-03-27 16:51:44 +0200544static void pipe_client_flush( struct fd *fd, struct event **event )
Mike McCormackef8b9462003-05-15 04:22:45 +0000545{
546 /* FIXME: what do we have to do for this? */
Mike McCormackef8b9462003-05-15 04:22:45 +0000547}
548
Robert Shearmane51dd362005-06-08 19:11:46 +0000549static inline int is_overlapped( unsigned int options )
Alexandre Julliard646d6212001-10-05 19:45:45 +0000550{
Robert Shearmane51dd362005-06-08 19:11:46 +0000551 return !(options & (FILE_SYNCHRONOUS_IO_ALERT | FILE_SYNCHRONOUS_IO_NONALERT));
552}
553
Alexandre Julliard89304272006-11-20 14:14:04 +0100554static enum server_fd_type pipe_server_get_info( struct fd *fd, int *flags )
Robert Shearmane51dd362005-06-08 19:11:46 +0000555{
556 struct pipe_server *server = get_fd_user( fd );
Robert Shearmane51dd362005-06-08 19:11:46 +0000557
Alexandre Julliard89304272006-11-20 14:14:04 +0100558 *flags = FD_FLAG_AVAILABLE;
559 if (is_overlapped( server->options )) *flags |= FD_FLAG_OVERLAPPED;
560 return FD_TYPE_PIPE;
Robert Shearmane51dd362005-06-08 19:11:46 +0000561}
562
Alexandre Julliard89304272006-11-20 14:14:04 +0100563static enum server_fd_type pipe_client_get_info( struct fd *fd, int *flags )
Robert Shearmane51dd362005-06-08 19:11:46 +0000564{
565 struct pipe_client *client = get_fd_user( fd );
Robert Shearmane51dd362005-06-08 19:11:46 +0000566
Alexandre Julliard89304272006-11-20 14:14:04 +0100567 *flags = FD_FLAG_AVAILABLE;
568 if (is_overlapped( client->flags )) *flags |= FD_FLAG_OVERLAPPED;
569 return FD_TYPE_PIPE;
Alexandre Julliard646d6212001-10-05 19:45:45 +0000570}
571
Vitaliy Margolenbabfa792005-12-05 13:09:35 +0100572static struct named_pipe *create_named_pipe( struct directory *root, const struct unicode_str *name,
573 unsigned int attr )
Alexandre Julliarde66207e2003-02-19 00:33:32 +0000574{
575 struct object *obj;
Vitaliy Margolenbabfa792005-12-05 13:09:35 +0100576 struct named_pipe *pipe = NULL;
577 struct unicode_str new_name;
Alexandre Julliarde66207e2003-02-19 00:33:32 +0000578
Vitaliy Margolenbabfa792005-12-05 13:09:35 +0100579 if (!name || !name->len) return alloc_object( &named_pipe_ops );
580
Alexandre Julliard50c48002007-03-22 14:40:41 +0100581 if (!(obj = find_object_dir( root, name, attr, &new_name )))
582 {
583 set_error( STATUS_OBJECT_NAME_INVALID );
584 return NULL;
585 }
Vitaliy Margolenbabfa792005-12-05 13:09:35 +0100586 if (!new_name.len)
Alexandre Julliarde66207e2003-02-19 00:33:32 +0000587 {
Vitaliy Margolenbabfa792005-12-05 13:09:35 +0100588 if (attr & OBJ_OPENIF && obj->ops == &named_pipe_ops)
589 set_error( STATUS_OBJECT_NAME_EXISTS );
590 else
591 {
592 release_object( obj );
593 obj = NULL;
594 if (attr & OBJ_OPENIF)
595 set_error( STATUS_OBJECT_TYPE_MISMATCH );
596 else
597 set_error( STATUS_OBJECT_NAME_COLLISION );
598 }
599 return (struct named_pipe *)obj;
Alexandre Julliarde66207e2003-02-19 00:33:32 +0000600 }
Alexandre Julliarde66207e2003-02-19 00:33:32 +0000601
Vitaliy Margolenbabfa792005-12-05 13:09:35 +0100602 if (obj->ops != &named_pipe_device_ops)
Alexandre Julliard50c48002007-03-22 14:40:41 +0100603 set_error( STATUS_OBJECT_NAME_INVALID );
Vitaliy Margolenbabfa792005-12-05 13:09:35 +0100604 else
605 {
606 struct named_pipe_device *dev = (struct named_pipe_device *)obj;
607 if ((pipe = create_object( dev->pipes, &named_pipe_ops, &new_name, NULL )))
608 clear_error();
609 }
610
611 release_object( obj );
612 return pipe;
Alexandre Julliarde66207e2003-02-19 00:33:32 +0000613}
614
Mike McCormackef8b9462003-05-15 04:22:45 +0000615static struct pipe_server *get_pipe_server_obj( struct process *process,
616 obj_handle_t handle, unsigned int access )
Mike McCormackde7c3002001-07-10 19:16:49 +0000617{
Mike McCormackef8b9462003-05-15 04:22:45 +0000618 struct object *obj;
619 obj = get_handle_obj( process, handle, access, &pipe_server_ops );
620 return (struct pipe_server *) obj;
Mike McCormackde7c3002001-07-10 19:16:49 +0000621}
622
Robert Shearmane51dd362005-06-08 19:11:46 +0000623static struct pipe_server *create_pipe_server( struct named_pipe *pipe, unsigned int options )
Mike McCormackde7c3002001-07-10 19:16:49 +0000624{
Mike McCormackef8b9462003-05-15 04:22:45 +0000625 struct pipe_server *server;
Mike McCormackde7c3002001-07-10 19:16:49 +0000626
Mike McCormackef8b9462003-05-15 04:22:45 +0000627 server = alloc_object( &pipe_server_ops );
Robert Shearman37957092005-06-10 19:54:46 +0000628 if (!server)
Mike McCormackde7c3002001-07-10 19:16:49 +0000629 return NULL;
Mike McCormackde7c3002001-07-10 19:16:49 +0000630
Mike McCormackef8b9462003-05-15 04:22:45 +0000631 server->fd = NULL;
632 server->pipe = pipe;
Alexandre Julliard7c1cf8f2005-02-03 10:48:23 +0000633 server->state = ps_idle_server;
Mike McCormackef8b9462003-05-15 04:22:45 +0000634 server->client = NULL;
635 server->flush_poll = NULL;
Robert Shearmane51dd362005-06-08 19:11:46 +0000636 server->options = options;
Alexandre Julliarddf09ac52007-04-02 20:09:29 +0200637 server->wait_q = create_async_queue( NULL );
Mike McCormackde7c3002001-07-10 19:16:49 +0000638
Alexandre Julliard7c1cf8f2005-02-03 10:48:23 +0000639 list_add_head( &pipe->servers, &server->entry );
Mike McCormackef8b9462003-05-15 04:22:45 +0000640 grab_object( pipe );
Mike McCormackde7c3002001-07-10 19:16:49 +0000641
Mike McCormackef8b9462003-05-15 04:22:45 +0000642 return server;
Mike McCormackde7c3002001-07-10 19:16:49 +0000643}
644
Robert Shearman43890d82006-06-07 20:11:59 +0100645static struct pipe_client *create_pipe_client( unsigned int flags )
Mike McCormackde7c3002001-07-10 19:16:49 +0000646{
Mike McCormackef8b9462003-05-15 04:22:45 +0000647 struct pipe_client *client;
Mike McCormackde7c3002001-07-10 19:16:49 +0000648
Mike McCormackef8b9462003-05-15 04:22:45 +0000649 client = alloc_object( &pipe_client_ops );
Robert Shearman37957092005-06-10 19:54:46 +0000650 if (!client)
Mike McCormackbf554572001-08-23 23:29:20 +0000651 return NULL;
652
Mike McCormackef8b9462003-05-15 04:22:45 +0000653 client->fd = NULL;
Robert Shearman43890d82006-06-07 20:11:59 +0100654 client->server = NULL;
Robert Shearmane51dd362005-06-08 19:11:46 +0000655 client->flags = flags;
Mike McCormackef8b9462003-05-15 04:22:45 +0000656
657 return client;
658}
659
Alexandre Julliard73e0e8b2007-03-23 14:03:23 +0100660static struct pipe_server *find_available_server( struct named_pipe *pipe )
Mike McCormackef8b9462003-05-15 04:22:45 +0000661{
Alexandre Julliard7c1cf8f2005-02-03 10:48:23 +0000662 struct pipe_server *server;
Mike McCormackef8b9462003-05-15 04:22:45 +0000663
Alexandre Julliard7c1cf8f2005-02-03 10:48:23 +0000664 LIST_FOR_EACH_ENTRY( server, &pipe->servers, struct pipe_server, entry )
665 {
Alexandre Julliard73e0e8b2007-03-23 14:03:23 +0100666 if (server->state == ps_idle_server || server->state == ps_wait_open)
Alexandre Julliard7c1cf8f2005-02-03 10:48:23 +0000667 return (struct pipe_server *)grab_object( server );
668 }
669 return NULL;
Mike McCormackde7c3002001-07-10 19:16:49 +0000670}
671
Alexandre Julliardde1866d2007-03-22 16:47:46 +0100672static struct object *named_pipe_open_file( struct object *obj, unsigned int access,
673 unsigned int sharing, unsigned int options )
674{
675 struct named_pipe *pipe = (struct named_pipe *)obj;
676 struct pipe_server *server;
677 struct pipe_client *client;
678 int fds[2];
679
Alexandre Julliard73e0e8b2007-03-23 14:03:23 +0100680 if (!(server = find_available_server( pipe )))
Alexandre Julliardde1866d2007-03-22 16:47:46 +0100681 {
682 set_error( STATUS_PIPE_NOT_AVAILABLE );
683 return NULL;
684 }
685
686 if ((client = create_pipe_client( options )))
687 {
688 if (!socketpair( PF_UNIX, SOCK_STREAM, 0, fds ))
689 {
690 int res = 0;
691
692 assert( !client->fd );
693 assert( !server->fd );
694
695 /* for performance reasons, only set nonblocking mode when using
696 * overlapped I/O. Otherwise, we will be doing too much busy
697 * looping */
698 if (is_overlapped( options ))
699 res = fcntl( fds[1], F_SETFL, O_NONBLOCK );
700 if ((res != -1) && is_overlapped( server->options ))
701 res = fcntl( fds[0], F_SETFL, O_NONBLOCK );
702
703 if (pipe->insize)
704 {
705 setsockopt( fds[0], SOL_SOCKET, SO_RCVBUF, &pipe->insize, sizeof(pipe->insize) );
706 setsockopt( fds[1], SOL_SOCKET, SO_RCVBUF, &pipe->insize, sizeof(pipe->insize) );
707 }
708 if (pipe->outsize)
709 {
710 setsockopt( fds[0], SOL_SOCKET, SO_SNDBUF, &pipe->outsize, sizeof(pipe->outsize) );
711 setsockopt( fds[1], SOL_SOCKET, SO_SNDBUF, &pipe->outsize, sizeof(pipe->outsize) );
712 }
713
714 client->fd = create_anonymous_fd( &pipe_client_fd_ops,
715 fds[1], &client->obj );
716 server->fd = create_anonymous_fd( &pipe_server_fd_ops,
717 fds[0], &server->obj );
718 if (client->fd && server->fd && res != 1)
719 {
720 if (server->state == ps_wait_open)
Alexandre Julliarddf09ac52007-04-02 20:09:29 +0200721 async_wake_up( server->wait_q, STATUS_SUCCESS );
Alexandre Julliardde1866d2007-03-22 16:47:46 +0100722 server->state = ps_connected_server;
723 server->client = client;
724 client->server = server;
725 }
726 }
727 else
728 file_set_error();
729 }
730 release_object( server );
731 return &client->obj;
732}
733
Mike McCormackde7c3002001-07-10 19:16:49 +0000734DECL_HANDLER(create_named_pipe)
735{
736 struct named_pipe *pipe;
Mike McCormackef8b9462003-05-15 04:22:45 +0000737 struct pipe_server *server;
Alexandre Julliardead9b062005-11-18 16:31:18 +0000738 struct unicode_str name;
Vitaliy Margolenbabfa792005-12-05 13:09:35 +0100739 struct directory *root = NULL;
Mike McCormackde7c3002001-07-10 19:16:49 +0000740
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000741 reply->handle = 0;
Alexandre Julliardead9b062005-11-18 16:31:18 +0000742 get_req_unicode_str( &name );
Vitaliy Margolenbabfa792005-12-05 13:09:35 +0100743 if (req->rootdir && !(root = get_directory_obj( current->process, req->rootdir, 0 )))
744 return;
745
746 pipe = create_named_pipe( root, &name, req->attributes | OBJ_OPENIF );
747
748 if (root) release_object( root );
749 if (!pipe) return;
Mike McCormackde7c3002001-07-10 19:16:49 +0000750
Vitaliy Margolen893987b2005-11-21 16:27:03 +0000751 if (get_error() != STATUS_OBJECT_NAME_EXISTS)
Mike McCormackf2e7ce72001-08-27 19:03:42 +0000752 {
Vitaliy Margolenbabfa792005-12-05 13:09:35 +0100753 /* initialize it if it didn't already exist */
754 pipe->instances = 0;
Alexandre Julliarddf09ac52007-04-02 20:09:29 +0200755 pipe->waiters = NULL;
Vitaliy Margolenbabfa792005-12-05 13:09:35 +0100756 list_init( &pipe->servers );
Mike McCormackf2e7ce72001-08-27 19:03:42 +0000757 pipe->insize = req->insize;
758 pipe->outsize = req->outsize;
759 pipe->maxinstances = req->maxinstances;
760 pipe->timeout = req->timeout;
Eric Pouech5a2591d2005-04-18 14:57:04 +0000761 pipe->flags = req->flags;
Mike McCormackf2e7ce72001-08-27 19:03:42 +0000762 }
Mike McCormackef8b9462003-05-15 04:22:45 +0000763 else
Mike McCormackde7c3002001-07-10 19:16:49 +0000764 {
Robert Shearman37957092005-06-10 19:54:46 +0000765 if (pipe->maxinstances <= pipe->instances)
Mike McCormackef8b9462003-05-15 04:22:45 +0000766 {
Vitaliy Margolenecca1042005-11-01 21:37:30 +0000767 set_error( STATUS_INSTANCE_NOT_AVAILABLE );
Mike McCormackef8b9462003-05-15 04:22:45 +0000768 release_object( pipe );
769 return;
770 }
Robert Shearman37957092005-06-10 19:54:46 +0000771 if ((pipe->maxinstances != req->maxinstances) ||
772 (pipe->timeout != req->timeout) ||
773 (pipe->flags != req->flags))
Mike McCormackef8b9462003-05-15 04:22:45 +0000774 {
775 set_error( STATUS_ACCESS_DENIED );
776 release_object( pipe );
777 return;
778 }
Eric Pouech1d6e2592006-05-26 12:10:11 +0200779 clear_error(); /* clear the name collision */
Mike McCormackef8b9462003-05-15 04:22:45 +0000780 }
781
Robert Shearmane51dd362005-06-08 19:11:46 +0000782 server = create_pipe_server( pipe, req->options );
Robert Shearman37957092005-06-10 19:54:46 +0000783 if (server)
Mike McCormackef8b9462003-05-15 04:22:45 +0000784 {
Alexandre Julliard24560e72005-12-09 13:58:25 +0100785 reply->handle = alloc_handle( current->process, server, req->access, req->attributes );
Mike McCormackef8b9462003-05-15 04:22:45 +0000786 server->pipe->instances++;
787 release_object( server );
Mike McCormackde7c3002001-07-10 19:16:49 +0000788 }
789
790 release_object( pipe );
791}
792
Mike McCormackde7c3002001-07-10 19:16:49 +0000793DECL_HANDLER(connect_named_pipe)
794{
Mike McCormackef8b9462003-05-15 04:22:45 +0000795 struct pipe_server *server;
Alexandre Julliard0aae1ca2007-04-02 20:41:59 +0200796 struct async *async;
Mike McCormackde7c3002001-07-10 19:16:49 +0000797
Mike McCormackef8b9462003-05-15 04:22:45 +0000798 server = get_pipe_server_obj(current->process, req->handle, 0);
Robert Shearman37957092005-06-10 19:54:46 +0000799 if (!server)
Mike McCormackde7c3002001-07-10 19:16:49 +0000800 return;
801
Robert Shearman37957092005-06-10 19:54:46 +0000802 switch(server->state)
Mike McCormackde7c3002001-07-10 19:16:49 +0000803 {
Mike McCormackef8b9462003-05-15 04:22:45 +0000804 case ps_idle_server:
805 case ps_wait_connect:
806 assert( !server->fd );
807 server->state = ps_wait_open;
Alexandre Julliard0aae1ca2007-04-02 20:41:59 +0200808 if ((async = create_async( current, server->wait_q, &req->async )))
809 {
810 if (server->pipe->waiters) async_wake_up( server->pipe->waiters, STATUS_SUCCESS );
811 release_object( async );
812 set_error( STATUS_PENDING );
813 }
Mike McCormackef8b9462003-05-15 04:22:45 +0000814 break;
815 case ps_connected_server:
816 assert( server->fd );
817 set_error( STATUS_PIPE_CONNECTED );
818 break;
819 case ps_disconnected_server:
820 set_error( STATUS_PIPE_BUSY );
821 break;
822 case ps_wait_disconnect:
823 set_error( STATUS_NO_DATA_DETECTED );
824 break;
Alexandre Julliard7c1cf8f2005-02-03 10:48:23 +0000825 case ps_wait_open:
Mike McCormackef8b9462003-05-15 04:22:45 +0000826 set_error( STATUS_INVALID_HANDLE );
827 break;
Mike McCormackde7c3002001-07-10 19:16:49 +0000828 }
829
Mike McCormackef8b9462003-05-15 04:22:45 +0000830 release_object(server);
Mike McCormackde7c3002001-07-10 19:16:49 +0000831}
Mike McCormackbf554572001-08-23 23:29:20 +0000832
833DECL_HANDLER(wait_named_pipe)
834{
Vitaliy Margolenb05340a2005-12-14 11:14:02 +0100835 struct named_pipe_device *device;
Mike McCormackbf554572001-08-23 23:29:20 +0000836 struct named_pipe *pipe;
Mike McCormackef8b9462003-05-15 04:22:45 +0000837 struct pipe_server *server;
Alexandre Julliardead9b062005-11-18 16:31:18 +0000838 struct unicode_str name;
Mike McCormackbf554572001-08-23 23:29:20 +0000839
Vitaliy Margolenb05340a2005-12-14 11:14:02 +0100840 device = (struct named_pipe_device *)get_handle_obj( current->process, req->handle,
841 FILE_READ_ATTRIBUTES, &named_pipe_device_ops );
842 if (!device) return;
843
Alexandre Julliardead9b062005-11-18 16:31:18 +0000844 get_req_unicode_str( &name );
Vitaliy Margolenb05340a2005-12-14 11:14:02 +0100845 pipe = (struct named_pipe *)find_object( device->pipes, &name, OBJ_CASE_INSENSITIVE );
846 release_object( device );
Vitaliy Margolenbabfa792005-12-05 13:09:35 +0100847 if (!pipe)
Mike McCormackbf554572001-08-23 23:29:20 +0000848 {
Alexandre Julliarde66207e2003-02-19 00:33:32 +0000849 set_error( STATUS_PIPE_NOT_AVAILABLE );
850 return;
Mike McCormackbf554572001-08-23 23:29:20 +0000851 }
Alexandre Julliard73e0e8b2007-03-23 14:03:23 +0100852 server = find_available_server( pipe );
Alexandre Julliarda133ad52007-03-21 14:31:54 +0100853 if (!server)
Robert Shearman795e9de2005-02-08 12:54:23 +0000854 {
Alexandre Julliard0aae1ca2007-04-02 20:41:59 +0200855 struct async *async;
856
Alexandre Julliarddf09ac52007-04-02 20:09:29 +0200857 if (!pipe->waiters && !(pipe->waiters = create_async_queue( NULL )))
858 {
859 release_object( pipe );
860 return;
861 }
Alexandre Julliard0aae1ca2007-04-02 20:41:59 +0200862
863 if ((async = create_async( current, pipe->waiters, &req->async )))
Alexandre Julliarda133ad52007-03-21 14:31:54 +0100864 {
Alexandre Julliard0aae1ca2007-04-02 20:41:59 +0200865 if (req->timeout != NMPWAIT_WAIT_FOREVER)
866 {
867 struct timeval when = current_time;
868 if (req->timeout == NMPWAIT_USE_DEFAULT_WAIT) add_timeout( &when, pipe->timeout );
869 else add_timeout( &when, req->timeout );
Alexandre Julliard4e5c7032007-04-03 19:12:31 +0200870 async_set_timeout( async, &when, STATUS_TIMEOUT );
Alexandre Julliard0aae1ca2007-04-02 20:41:59 +0200871 }
872 release_object( async );
873 set_error( STATUS_PENDING );
Alexandre Julliard40723f72006-07-26 11:47:42 +0200874 }
Robert Shearman795e9de2005-02-08 12:54:23 +0000875 }
Alexandre Julliarda133ad52007-03-21 14:31:54 +0100876 else release_object( server );
Alexandre Julliarde66207e2003-02-19 00:33:32 +0000877
Mike McCormackef8b9462003-05-15 04:22:45 +0000878 release_object( pipe );
Mike McCormackbf554572001-08-23 23:29:20 +0000879}
880
881DECL_HANDLER(disconnect_named_pipe)
882{
Mike McCormackef8b9462003-05-15 04:22:45 +0000883 struct pipe_server *server;
Mike McCormackbf554572001-08-23 23:29:20 +0000884
Mike McCormackef8b9462003-05-15 04:22:45 +0000885 server = get_pipe_server_obj( current->process, req->handle, 0 );
Robert Shearman37957092005-06-10 19:54:46 +0000886 if (!server)
Mike McCormackbf554572001-08-23 23:29:20 +0000887 return;
Robert Shearman37957092005-06-10 19:54:46 +0000888 switch(server->state)
Mike McCormackbf554572001-08-23 23:29:20 +0000889 {
Mike McCormackef8b9462003-05-15 04:22:45 +0000890 case ps_connected_server:
891 assert( server->fd );
892 assert( server->client );
893 assert( server->client->fd );
Mike McCormackbf554572001-08-23 23:29:20 +0000894
Mike McCormackef8b9462003-05-15 04:22:45 +0000895 notify_empty( server );
Mike McCormackef8b9462003-05-15 04:22:45 +0000896
897 /* Dump the client and server fds, but keep the pointers
898 around - client loses all waiting data */
899 server->state = ps_disconnected_server;
900 do_disconnect( server );
Mike McCormackef8b9462003-05-15 04:22:45 +0000901 break;
902
903 case ps_wait_disconnect:
904 assert( !server->client );
905 assert( server->fd );
906 do_disconnect( server );
907 server->state = ps_wait_connect;
Mike McCormackef8b9462003-05-15 04:22:45 +0000908 break;
909
Alexandre Julliard7c1cf8f2005-02-03 10:48:23 +0000910 case ps_idle_server:
911 case ps_wait_open:
912 case ps_disconnected_server:
913 case ps_wait_connect:
Mike McCormackef8b9462003-05-15 04:22:45 +0000914 set_error( STATUS_PIPE_DISCONNECTED );
Alexandre Julliard7c1cf8f2005-02-03 10:48:23 +0000915 break;
Mike McCormackbf554572001-08-23 23:29:20 +0000916 }
Mike McCormackef8b9462003-05-15 04:22:45 +0000917 release_object( server );
Mike McCormackbf554572001-08-23 23:29:20 +0000918}
Mike McCormackf2e7ce72001-08-27 19:03:42 +0000919
920DECL_HANDLER(get_named_pipe_info)
921{
Mike McCormackef8b9462003-05-15 04:22:45 +0000922 struct pipe_server *server;
Eric Pouech1d6e2592006-05-26 12:10:11 +0200923 struct pipe_client *client = NULL;
Mike McCormackf2e7ce72001-08-27 19:03:42 +0000924
Eric Pouech1d6e2592006-05-26 12:10:11 +0200925 server = get_pipe_server_obj( current->process, req->handle, FILE_READ_ATTRIBUTES );
Robert Shearman37957092005-06-10 19:54:46 +0000926 if (!server)
Eric Pouech1d6e2592006-05-26 12:10:11 +0200927 {
928 clear_error();
929 client = (struct pipe_client *)get_handle_obj( current->process, req->handle,
930 FILE_READ_ATTRIBUTES, &pipe_client_ops );
931 if (!client) return;
932 server = client->server;
933 }
Mike McCormackf2e7ce72001-08-27 19:03:42 +0000934
Eric Pouech5a2591d2005-04-18 14:57:04 +0000935 reply->flags = server->pipe->flags;
Mike McCormackef8b9462003-05-15 04:22:45 +0000936 reply->maxinstances = server->pipe->maxinstances;
Eric Pouech1d6e2592006-05-26 12:10:11 +0200937 reply->instances = server->pipe->instances;
Mike McCormackef8b9462003-05-15 04:22:45 +0000938 reply->insize = server->pipe->insize;
939 reply->outsize = server->pipe->outsize;
Mike McCormackf2e7ce72001-08-27 19:03:42 +0000940
Eric Pouech1d6e2592006-05-26 12:10:11 +0200941 if (client)
942 release_object(client);
943 else
944 {
945 reply->flags |= NAMED_PIPE_SERVER_END;
946 release_object(server);
947 }
Mike McCormackf2e7ce72001-08-27 19:03:42 +0000948}