wininet: Don't discard the extra info part of a URL in InternetOpenUrl.
[wine] / server / named_pipe.c
1 /*
2  * Server-side pipe management
3  *
4  * Copyright (C) 1998 Alexandre Julliard
5  * Copyright (C) 2001 Mike McCormack
6  *
7  * 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
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20  *
21  * TODO:
22  *   message mode
23  */
24
25 #include "config.h"
26 #include "wine/port.h"
27
28 #include <assert.h>
29 #include <fcntl.h>
30 #include <string.h>
31 #include <stdarg.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <sys/time.h>
35 #include <sys/types.h>
36 #ifdef HAVE_SYS_SOCKET_H
37 #include <sys/socket.h>
38 #endif
39 #include <time.h>
40 #include <unistd.h>
41 #ifdef HAVE_POLL_H
42 #include <poll.h>
43 #endif
44
45 #include "ntstatus.h"
46 #define WIN32_NO_STATUS
47 #include "windef.h"
48 #include "winternl.h"
49
50 #include "file.h"
51 #include "handle.h"
52 #include "thread.h"
53 #include "request.h"
54
55 enum pipe_state
56 {
57     ps_idle_server,
58     ps_wait_open,
59     ps_connected_server,
60     ps_wait_disconnect,
61     ps_disconnected_server,
62     ps_wait_connect
63 };
64
65 struct named_pipe;
66
67 struct pipe_server
68 {
69     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 */
74     struct named_pipe   *pipe;
75     struct timeout_user *flush_poll;
76     struct event        *event;
77     struct list          wait_q;     /* only a single one can be queued */
78     unsigned int         options;    /* pipe options */
79 };
80
81 struct pipe_client
82 {
83     struct object        obj;        /* object header */
84     struct fd           *fd;         /* pipe file descriptor */
85     struct pipe_server  *server;     /* server that this client is connected to */
86     unsigned int         flags;      /* file flags */
87 };
88
89 struct named_pipe
90 {
91     struct object       obj;         /* object header */
92     unsigned int        flags;
93     unsigned int        maxinstances;
94     unsigned int        outsize;
95     unsigned int        insize;
96     unsigned int        timeout;
97     unsigned int        instances;
98     struct list         servers;     /* list of servers using this pipe */
99     struct list         waiters;     /* list of clients waiting to connect */
100 };
101
102 struct named_pipe_device
103 {
104     struct object       obj;         /* object header */
105     struct fd          *fd;          /* pseudo-fd for ioctls */
106     struct namespace   *pipes;       /* named pipe namespace */
107 };
108
109 static void named_pipe_dump( struct object *obj, int verbose );
110 static unsigned int named_pipe_map_access( struct object *obj, unsigned int access );
111 static void named_pipe_destroy( struct object *obj );
112
113 static const struct object_ops named_pipe_ops =
114 {
115     sizeof(struct named_pipe),    /* size */
116     named_pipe_dump,              /* dump */
117     no_add_queue,                 /* add_queue */
118     NULL,                         /* remove_queue */
119     NULL,                         /* signaled */
120     NULL,                         /* satisfied */
121     no_signal,                    /* signal */
122     no_get_fd,                    /* get_fd */
123     named_pipe_map_access,        /* map_access */
124     no_lookup_name,               /* lookup_name */
125     no_close_handle,              /* close_handle */
126     named_pipe_destroy            /* destroy */
127 };
128
129 /* functions common to server and client */
130 static unsigned int pipe_map_access( struct object *obj, unsigned int access );
131
132 /* server end functions */
133 static void pipe_server_dump( struct object *obj, int verbose );
134 static struct fd *pipe_server_get_fd( struct object *obj );
135 static void pipe_server_destroy( struct object *obj);
136 static int pipe_server_flush( struct fd *fd, struct event **event );
137 static enum server_fd_type pipe_server_get_info( struct fd *fd, int *flags );
138
139 static const struct object_ops pipe_server_ops =
140 {
141     sizeof(struct pipe_server),   /* size */
142     pipe_server_dump,             /* dump */
143     default_fd_add_queue,         /* add_queue */
144     default_fd_remove_queue,      /* remove_queue */
145     default_fd_signaled,          /* signaled */
146     no_satisfied,                 /* satisfied */
147     no_signal,                    /* signal */
148     pipe_server_get_fd,           /* get_fd */
149     pipe_map_access,              /* map_access */
150     no_lookup_name,               /* lookup_name */
151     fd_close_handle,              /* close_handle */
152     pipe_server_destroy           /* destroy */
153 };
154
155 static const struct fd_ops pipe_server_fd_ops =
156 {
157     default_fd_get_poll_events,     /* get_poll_events */
158     default_poll_event,           /* poll_event */
159     pipe_server_flush,            /* flush */
160     pipe_server_get_info,         /* get_file_info */
161     default_fd_queue_async,       /* queue_async */
162     default_fd_cancel_async,      /* cancel_async */
163 };
164
165 /* client end functions */
166 static void pipe_client_dump( struct object *obj, int verbose );
167 static struct fd *pipe_client_get_fd( struct object *obj );
168 static void pipe_client_destroy( struct object *obj );
169 static int pipe_client_flush( struct fd *fd, struct event **event );
170 static enum server_fd_type pipe_client_get_info( struct fd *fd, int *flags );
171
172 static const struct object_ops pipe_client_ops =
173 {
174     sizeof(struct pipe_client),   /* size */
175     pipe_client_dump,             /* dump */
176     default_fd_add_queue,         /* add_queue */
177     default_fd_remove_queue,      /* remove_queue */
178     default_fd_signaled,          /* signaled */
179     no_satisfied,                 /* satisfied */
180     no_signal,                    /* signal */
181     pipe_client_get_fd,           /* get_fd */
182     pipe_map_access,              /* map_access */
183     no_lookup_name,               /* lookup_name */
184     fd_close_handle,              /* close_handle */
185     pipe_client_destroy           /* destroy */
186 };
187
188 static const struct fd_ops pipe_client_fd_ops =
189 {
190     default_fd_get_poll_events,   /* get_poll_events */
191     default_poll_event,           /* poll_event */
192     pipe_client_flush,            /* flush */
193     pipe_client_get_info,         /* get_file_info */
194     default_fd_queue_async,       /* queue_async */
195     default_fd_cancel_async       /* cancel_async */
196 };
197
198 static void named_pipe_device_dump( struct object *obj, int verbose );
199 static struct fd *named_pipe_device_get_fd( struct object *obj );
200 static struct object *named_pipe_device_lookup_name( struct object *obj,
201     struct unicode_str *name, unsigned int attr );
202 static void named_pipe_device_destroy( struct object *obj );
203 static enum server_fd_type named_pipe_device_get_file_info( struct fd *fd, int *flags );
204
205 static const struct object_ops named_pipe_device_ops =
206 {
207     sizeof(struct named_pipe_device), /* size */
208     named_pipe_device_dump,           /* dump */
209     no_add_queue,                     /* add_queue */
210     NULL,                             /* remove_queue */
211     NULL,                             /* signaled */
212     no_satisfied,                     /* satisfied */
213     no_signal,                        /* signal */
214     named_pipe_device_get_fd,         /* get_fd */
215     pipe_map_access,                  /* map_access */
216     named_pipe_device_lookup_name,    /* lookup_name */
217     fd_close_handle,                  /* close_handle */
218     named_pipe_device_destroy         /* destroy */
219 };
220
221 static const struct fd_ops named_pipe_device_fd_ops =
222 {
223     default_fd_get_poll_events,       /* get_poll_events */
224     default_poll_event,               /* poll_event */
225     no_flush,                         /* flush */
226     named_pipe_device_get_file_info,  /* get_file_info */
227     default_fd_queue_async,           /* queue_async */
228     default_fd_cancel_async           /* cancel_async */
229 };
230
231 static void named_pipe_dump( struct object *obj, int verbose )
232 {
233     struct named_pipe *pipe = (struct named_pipe *) obj;
234     assert( obj->ops == &named_pipe_ops );
235     fprintf( stderr, "Named pipe " );
236     dump_object_name( &pipe->obj );
237     fprintf( stderr, "\n" );
238 }
239
240 static unsigned int named_pipe_map_access( struct object *obj, unsigned int access )
241 {
242     if (access & GENERIC_READ)    access |= STANDARD_RIGHTS_READ;
243     if (access & GENERIC_WRITE)   access |= STANDARD_RIGHTS_WRITE | FILE_CREATE_PIPE_INSTANCE;
244     if (access & GENERIC_EXECUTE) access |= STANDARD_RIGHTS_EXECUTE;
245     if (access & GENERIC_ALL)     access |= STANDARD_RIGHTS_ALL;
246     return access & ~(GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE | GENERIC_ALL);
247 }
248
249 static void pipe_server_dump( struct object *obj, int verbose )
250 {
251     struct pipe_server *server = (struct pipe_server *) obj;
252     assert( obj->ops == &pipe_server_ops );
253     fprintf( stderr, "Named pipe server pipe=%p state=%d\n", server->pipe, server->state );
254 }
255
256 static void pipe_client_dump( struct object *obj, int verbose )
257 {
258     struct pipe_client *client = (struct pipe_client *) obj;
259     assert( obj->ops == &pipe_client_ops );
260     fprintf( stderr, "Named pipe client server=%p\n", client->server );
261 }
262
263 static void named_pipe_destroy( struct object *obj)
264 {
265     struct named_pipe *pipe = (struct named_pipe *) obj;
266
267     assert( list_empty( &pipe->servers ) );
268     assert( !pipe->instances );
269     async_terminate_queue( &pipe->waiters, STATUS_HANDLES_CLOSED );
270 }
271
272 static struct fd *pipe_client_get_fd( struct object *obj )
273 {
274     struct pipe_client *client = (struct pipe_client *) obj;
275     if (client->fd)
276         return (struct fd *) grab_object( client->fd );
277     set_error( STATUS_PIPE_DISCONNECTED );
278     return NULL;
279 }
280
281 static struct fd *pipe_server_get_fd( struct object *obj )
282 {
283     struct pipe_server *server = (struct pipe_server *) obj;
284
285     switch(server->state)
286     {
287     case ps_connected_server:
288     case ps_wait_disconnect:
289         assert( server->fd );
290         return (struct fd *) grab_object( server->fd );
291
292     case ps_wait_open:
293     case ps_idle_server:
294         set_error( STATUS_PIPE_LISTENING );
295         break;
296
297     case ps_disconnected_server:
298     case ps_wait_connect:
299         set_error( STATUS_PIPE_DISCONNECTED );
300         break;
301     }
302     return NULL;
303 }
304
305
306 static void notify_empty( struct pipe_server *server )
307 {
308     if (!server->flush_poll)
309         return;
310     assert( server->state == ps_connected_server );
311     assert( server->event );
312     remove_timeout_user( server->flush_poll );
313     server->flush_poll = NULL;
314     set_event( server->event );
315     release_object( server->event );
316     server->event = NULL;
317 }
318
319 static void do_disconnect( struct pipe_server *server )
320 {
321     /* we may only have a server fd, if the client disconnected */
322     if (server->client)
323     {
324         assert( server->client->server == server );
325         assert( server->client->fd );
326         release_object( server->client->fd );
327         server->client->fd = NULL;
328     }
329     assert( server->fd );
330     release_object( server->fd );
331     server->fd = NULL;
332 }
333
334 static unsigned int pipe_map_access( struct object *obj, unsigned int access )
335 {
336     if (access & GENERIC_READ)    access |= FILE_GENERIC_READ;
337     if (access & GENERIC_WRITE)   access |= FILE_GENERIC_WRITE;
338     if (access & GENERIC_EXECUTE) access |= FILE_GENERIC_EXECUTE;
339     if (access & GENERIC_ALL)     access |= FILE_ALL_ACCESS;
340     return access & ~(GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE | GENERIC_ALL);
341 }
342
343 static void pipe_server_destroy( struct object *obj)
344 {
345     struct pipe_server *server = (struct pipe_server *)obj;
346
347     assert( obj->ops == &pipe_server_ops );
348
349     if (server->fd)
350     {
351         notify_empty( server );
352         do_disconnect( server );
353     }
354
355     if (server->client)
356     {
357         server->client->server = NULL;
358         server->client = NULL;
359     }
360
361     async_terminate_head( &server->wait_q, STATUS_HANDLES_CLOSED );
362
363     assert( server->pipe->instances );
364     server->pipe->instances--;
365
366     list_remove( &server->entry );
367     release_object( server->pipe );
368 }
369
370 static void pipe_client_destroy( struct object *obj)
371 {
372     struct pipe_client *client = (struct pipe_client *)obj;
373     struct pipe_server *server = client->server;
374
375     assert( obj->ops == &pipe_client_ops );
376
377     if (server)
378     {
379         notify_empty( server );
380
381         switch(server->state)
382         {
383         case ps_connected_server:
384             /* Don't destroy the server's fd here as we can't
385                do a successful flush without it. */
386             server->state = ps_wait_disconnect;
387             release_object( client->fd );
388             client->fd = NULL;
389             break;
390         case ps_disconnected_server:
391             server->state = ps_wait_connect;
392             break;
393         case ps_idle_server:
394         case ps_wait_open:
395         case ps_wait_disconnect:
396         case ps_wait_connect:
397             assert( 0 );
398         }
399         assert( server->client );
400         server->client = NULL;
401         client->server = NULL;
402     }
403     assert( !client->fd );
404 }
405
406 static void named_pipe_device_dump( struct object *obj, int verbose )
407 {
408     assert( obj->ops == &named_pipe_device_ops );
409     fprintf( stderr, "Named pipe device\n" );
410 }
411
412 static struct fd *named_pipe_device_get_fd( struct object *obj )
413 {
414     struct named_pipe_device *device = (struct named_pipe_device *)obj;
415     return (struct fd *)grab_object( device->fd );
416 }
417
418 static struct object *named_pipe_device_lookup_name( struct object *obj, struct unicode_str *name,
419                                                      unsigned int attr )
420 {
421     struct named_pipe_device *device = (struct named_pipe_device*)obj;
422     struct object *found;
423
424     assert( obj->ops == &named_pipe_device_ops );
425     assert( device->pipes );
426
427     if ((found = find_object( device->pipes, name, attr | OBJ_CASE_INSENSITIVE )))
428         name->len = 0;
429
430     return found;
431 }
432
433 static void named_pipe_device_destroy( struct object *obj )
434 {
435     struct named_pipe_device *device = (struct named_pipe_device*)obj;
436     assert( obj->ops == &named_pipe_device_ops );
437     if (device->fd) release_object( device->fd );
438     free( device->pipes );
439 }
440
441 static enum server_fd_type named_pipe_device_get_file_info( struct fd *fd, int *flags )
442 {
443     *flags = 0;
444     return FD_TYPE_DEVICE;
445 }
446
447 void create_named_pipe_device( struct directory *root, const struct unicode_str *name )
448 {
449     struct named_pipe_device *dev;
450
451     if ((dev = create_named_object_dir( root, name, 0, &named_pipe_device_ops )) &&
452         get_error() != STATUS_OBJECT_NAME_EXISTS)
453     {
454         dev->pipes = NULL;
455         if (!(dev->fd = alloc_pseudo_fd( &named_pipe_device_fd_ops, &dev->obj )) ||
456             !(dev->pipes = create_namespace( 7 )))
457         {
458             release_object( dev );
459             dev = NULL;
460         }
461     }
462     if (dev) make_object_static( &dev->obj );
463 }
464
465 static int pipe_data_remaining( struct pipe_server *server )
466 {
467     struct pollfd pfd;
468     int fd;
469
470     assert( server->client );
471
472     fd = get_unix_fd( server->client->fd );
473     if (fd < 0)
474         return 0;
475     pfd.fd = fd;
476     pfd.events = POLLIN;
477     pfd.revents = 0;
478
479     if (0 > poll( &pfd, 1, 0 ))
480         return 0;
481  
482     return pfd.revents&POLLIN;
483 }
484
485 static void check_flushed( void *arg )
486 {
487     struct pipe_server *server = (struct pipe_server*) arg;
488
489     assert( server->event );
490     if (pipe_data_remaining( server ))
491     {
492         struct timeval tv = current_time;
493         add_timeout( &tv, 100 );
494         server->flush_poll = add_timeout_user( &tv, check_flushed, server );
495     }
496     else
497     {
498         /* notify_empty( server ); */
499         server->flush_poll = NULL;
500         set_event( server->event );
501         release_object( server->event );
502         server->event = NULL;
503     }
504 }
505
506 static int pipe_server_flush( struct fd *fd, struct event **event )
507 {
508     struct pipe_server *server = get_fd_user( fd );
509
510     if (!server)
511         return 0;
512
513     if (server->state != ps_connected_server)
514         return 0;
515
516     /* FIXME: if multiple threads flush the same pipe,
517               maybe should create a list of processes to notify */
518     if (server->flush_poll)
519         return 0;
520
521     if (pipe_data_remaining( server ))
522     {
523         struct timeval tv = current_time;
524
525         /* this kind of sux - 
526            there's no unix way to be alerted when a pipe becomes empty */
527         server->event = create_event( NULL, NULL, 0, 0, 0 );
528         if (!server->event)
529             return 0;
530         add_timeout( &tv, 100 );
531         server->flush_poll = add_timeout_user( &tv, check_flushed, server );
532         *event = server->event;
533     }
534
535     return 0; 
536 }
537
538 static int pipe_client_flush( struct fd *fd, struct event **event )
539 {
540     /* FIXME: what do we have to do for this? */
541     return 0;
542 }
543
544 static inline int is_overlapped( unsigned int options )
545 {
546     return !(options & (FILE_SYNCHRONOUS_IO_ALERT | FILE_SYNCHRONOUS_IO_NONALERT));
547 }
548
549 static enum server_fd_type pipe_server_get_info( struct fd *fd, int *flags )
550 {
551     struct pipe_server *server = get_fd_user( fd );
552
553     *flags = FD_FLAG_AVAILABLE;
554     if (is_overlapped( server->options )) *flags |= FD_FLAG_OVERLAPPED;
555     return FD_TYPE_PIPE;
556 }
557
558 static enum server_fd_type pipe_client_get_info( struct fd *fd, int *flags )
559 {
560     struct pipe_client *client = get_fd_user( fd );
561
562     *flags = FD_FLAG_AVAILABLE;
563     if (is_overlapped( client->flags )) *flags |= FD_FLAG_OVERLAPPED;
564     return FD_TYPE_PIPE;
565 }
566
567 static struct named_pipe *create_named_pipe( struct directory *root, const struct unicode_str *name,
568                                              unsigned int attr )
569 {
570     struct object *obj;
571     struct named_pipe *pipe = NULL;
572     struct unicode_str new_name;
573
574     if (!name || !name->len) return alloc_object( &named_pipe_ops );
575
576     if (!(obj = find_object_dir( root, name, attr, &new_name ))) return NULL;
577     if (!new_name.len)
578     {
579         if (attr & OBJ_OPENIF && obj->ops == &named_pipe_ops)
580             set_error( STATUS_OBJECT_NAME_EXISTS );
581         else
582         {
583             release_object( obj );
584             obj = NULL;
585             if (attr & OBJ_OPENIF)
586                 set_error( STATUS_OBJECT_TYPE_MISMATCH );
587             else
588                 set_error( STATUS_OBJECT_NAME_COLLISION );
589         }
590         return (struct named_pipe *)obj;
591     }
592
593     if (obj->ops != &named_pipe_device_ops)
594         set_error( STATUS_OBJECT_TYPE_MISMATCH );
595     else
596     {
597         struct named_pipe_device *dev = (struct named_pipe_device *)obj;
598         if ((pipe = create_object( dev->pipes, &named_pipe_ops, &new_name, NULL )))
599             clear_error();
600     }
601
602     release_object( obj );
603     return pipe;
604 }
605
606 static struct pipe_server *get_pipe_server_obj( struct process *process,
607                                 obj_handle_t handle, unsigned int access )
608 {
609     struct object *obj;
610     obj = get_handle_obj( process, handle, access, &pipe_server_ops );
611     return (struct pipe_server *) obj;
612 }
613
614 static struct pipe_server *create_pipe_server( struct named_pipe *pipe, unsigned int options )
615 {
616     struct pipe_server *server;
617
618     server = alloc_object( &pipe_server_ops );
619     if (!server)
620         return NULL;
621
622     server->fd = NULL;
623     server->pipe = pipe;
624     server->state = ps_idle_server;
625     server->client = NULL;
626     server->flush_poll = NULL;
627     server->options = options;
628     list_init( &server->wait_q );
629
630     list_add_head( &pipe->servers, &server->entry );
631     grab_object( pipe );
632
633     return server;
634 }
635
636 static struct pipe_client *create_pipe_client( unsigned int flags )
637 {
638     struct pipe_client *client;
639
640     client = alloc_object( &pipe_client_ops );
641     if (!client)
642         return NULL;
643
644     client->fd = NULL;
645     client->server = NULL;
646     client->flags = flags;
647
648     return client;
649 }
650
651 static inline struct pipe_server *find_server( struct named_pipe *pipe, enum pipe_state state )
652 {
653     struct pipe_server *server;
654
655     LIST_FOR_EACH_ENTRY( server, &pipe->servers, struct pipe_server, entry )
656     {
657         if (server->state == state) return (struct pipe_server *)grab_object( server );
658     }
659     return NULL;
660 }
661
662 static inline struct pipe_server *find_server2( struct named_pipe *pipe,
663                                                 enum pipe_state state1, enum pipe_state state2 )
664 {
665     struct pipe_server *server;
666
667     LIST_FOR_EACH_ENTRY( server, &pipe->servers, struct pipe_server, entry )
668     {
669         if (server->state == state1 || server->state == state2)
670             return (struct pipe_server *)grab_object( server );
671     }
672     return NULL;
673 }
674
675 DECL_HANDLER(create_named_pipe)
676 {
677     struct named_pipe *pipe;
678     struct pipe_server *server;
679     struct unicode_str name;
680     struct directory *root = NULL;
681
682     reply->handle = 0;
683     get_req_unicode_str( &name );
684     if (req->rootdir && !(root = get_directory_obj( current->process, req->rootdir, 0 )))
685         return;
686
687     pipe = create_named_pipe( root, &name, req->attributes | OBJ_OPENIF );
688
689     if (root) release_object( root );
690     if (!pipe) return;
691
692     if (get_error() != STATUS_OBJECT_NAME_EXISTS)
693     {
694         /* initialize it if it didn't already exist */
695         pipe->instances = 0;
696         list_init( &pipe->servers );
697         list_init( &pipe->waiters );
698         pipe->insize = req->insize;
699         pipe->outsize = req->outsize;
700         pipe->maxinstances = req->maxinstances;
701         pipe->timeout = req->timeout;
702         pipe->flags = req->flags;
703     }
704     else
705     {
706         if (pipe->maxinstances <= pipe->instances)
707         {
708             set_error( STATUS_INSTANCE_NOT_AVAILABLE );
709             release_object( pipe );
710             return;
711         }
712         if ((pipe->maxinstances != req->maxinstances) ||
713             (pipe->timeout != req->timeout) ||
714             (pipe->flags != req->flags))
715         {
716             set_error( STATUS_ACCESS_DENIED );
717             release_object( pipe );
718             return;
719         }
720         clear_error(); /* clear the name collision */
721     }
722
723     server = create_pipe_server( pipe, req->options );
724     if (server)
725     {
726         reply->handle = alloc_handle( current->process, server, req->access, req->attributes );
727         server->pipe->instances++;
728         release_object( server );
729     }
730
731     release_object( pipe );
732 }
733
734 DECL_HANDLER(open_named_pipe)
735 {
736     struct pipe_server *server;
737     struct pipe_client *client;
738     struct unicode_str name;
739     struct directory *root = NULL;
740     struct named_pipe *pipe;
741     int fds[2];
742
743     get_req_unicode_str( &name );
744     if (req->rootdir && !(root = get_directory_obj( current->process, req->rootdir, 0 )))
745         return;
746
747     pipe = open_object_dir( root, &name, req->attributes, &named_pipe_ops );
748
749     if (root) release_object( root );
750     if (!pipe) return;
751
752     server = find_server2( pipe, ps_idle_server, ps_wait_open );
753     release_object( pipe );
754
755     if (!server)
756     {
757         set_error( STATUS_PIPE_NOT_AVAILABLE );
758         return;
759     }
760
761     client = create_pipe_client( req->flags );
762     if (client)
763     {
764         if (!socketpair( PF_UNIX, SOCK_STREAM, 0, fds ))
765         {
766             int res = 0;
767
768             assert( !client->fd );
769             assert( !server->fd );
770
771             /* for performance reasons, only set nonblocking mode when using
772              * overlapped I/O. Otherwise, we will be doing too much busy
773              * looping */
774             if (is_overlapped( req->flags ))
775                 res = fcntl( fds[1], F_SETFL, O_NONBLOCK );
776             if ((res != -1) && is_overlapped( server->options ))
777                 res = fcntl( fds[0], F_SETFL, O_NONBLOCK );
778
779             if (pipe->insize)
780             {
781                 setsockopt( fds[0], SOL_SOCKET, SO_RCVBUF, &pipe->insize, sizeof(pipe->insize) );
782                 setsockopt( fds[1], SOL_SOCKET, SO_RCVBUF, &pipe->insize, sizeof(pipe->insize) );
783             }
784             if (pipe->outsize)
785             {
786                 setsockopt( fds[0], SOL_SOCKET, SO_SNDBUF, &pipe->outsize, sizeof(pipe->outsize) );
787                 setsockopt( fds[1], SOL_SOCKET, SO_SNDBUF, &pipe->outsize, sizeof(pipe->outsize) );
788             }
789
790             client->fd = create_anonymous_fd( &pipe_client_fd_ops,
791                                             fds[1], &client->obj );
792             server->fd = create_anonymous_fd( &pipe_server_fd_ops,
793                                             fds[0], &server->obj );
794             if (client->fd && server->fd && res != 1)
795             {
796                 if (server->state == ps_wait_open)
797                     async_terminate_head( &server->wait_q, STATUS_SUCCESS );
798                 assert( list_empty( &server->wait_q ) );
799                 server->state = ps_connected_server;
800                 server->client = client;
801                 client->server = server;
802                 reply->handle = alloc_handle( current->process, client, req->access, req->attributes );
803             }
804         }
805         else
806             file_set_error();
807
808         release_object( client );
809     }
810     release_object( server );
811 }
812
813 DECL_HANDLER(connect_named_pipe)
814 {
815     struct pipe_server *server;
816
817     server = get_pipe_server_obj(current->process, req->handle, 0);
818     if (!server)
819         return;
820
821     switch(server->state)
822     {
823     case ps_idle_server:
824     case ps_wait_connect:
825         assert( !server->fd );
826         server->state = ps_wait_open;
827         create_async( current, NULL, &server->wait_q,
828                       req->func, req->event, NULL );
829         async_terminate_queue( &server->pipe->waiters, STATUS_SUCCESS );
830         break;
831     case ps_connected_server:
832         assert( server->fd );
833         set_error( STATUS_PIPE_CONNECTED );
834         break;
835     case ps_disconnected_server:
836         set_error( STATUS_PIPE_BUSY );
837         break;
838     case ps_wait_disconnect:
839         set_error( STATUS_NO_DATA_DETECTED );
840         break;
841     case ps_wait_open:
842         set_error( STATUS_INVALID_HANDLE );
843         break;
844     }
845
846     release_object(server);
847 }
848
849 DECL_HANDLER(wait_named_pipe)
850 {
851     struct named_pipe_device *device;
852     struct named_pipe *pipe;
853     struct pipe_server *server;
854     struct unicode_str name;
855
856     device = (struct named_pipe_device *)get_handle_obj( current->process, req->handle,
857                                                          FILE_READ_ATTRIBUTES, &named_pipe_device_ops );
858     if (!device) return;
859
860     get_req_unicode_str( &name );
861     pipe = (struct named_pipe *)find_object( device->pipes, &name, OBJ_CASE_INSENSITIVE );
862     release_object( device );
863     if (!pipe)
864     {
865         set_error( STATUS_PIPE_NOT_AVAILABLE );
866         return;
867     }
868     server = find_server( pipe, ps_wait_open );
869     if (server)
870     {
871         apc_call_t data;
872
873         /* there's already a server waiting for a client to connect */
874         memset( &data, 0, sizeof(data) );
875         data.type            = APC_ASYNC_IO;
876         data.async_io.func   = req->func;
877         data.async_io.user   = req->event;
878         data.async_io.sb     = NULL;
879         data.async_io.status = STATUS_SUCCESS;
880         thread_queue_apc( current, NULL, &data );
881         release_object( server );
882     }
883     else
884     {
885         if (req->timeout == NMPWAIT_WAIT_FOREVER)
886             create_async( current, NULL, &pipe->waiters,
887                           req->func, req->event, NULL );
888         else
889         {
890             struct timeval when = current_time;
891             if (req->timeout == NMPWAIT_USE_DEFAULT_WAIT) add_timeout( &when, pipe->timeout );
892             else add_timeout( &when, req->timeout );
893             create_async( current, &when, &pipe->waiters, req->func, req->event, NULL );
894         }
895     }
896
897     release_object( pipe );
898 }
899
900 DECL_HANDLER(disconnect_named_pipe)
901 {
902     struct pipe_server *server;
903
904     server = get_pipe_server_obj( current->process, req->handle, 0 );
905     if (!server)
906         return;
907     switch(server->state)
908     {
909     case ps_connected_server:
910         assert( server->fd );
911         assert( server->client );
912         assert( server->client->fd );
913
914         notify_empty( server );
915
916         /* Dump the client and server fds, but keep the pointers
917            around - client loses all waiting data */
918         server->state = ps_disconnected_server;
919         do_disconnect( server );
920         break;
921
922     case ps_wait_disconnect:
923         assert( !server->client );
924         assert( server->fd );
925         do_disconnect( server );
926         server->state = ps_wait_connect;
927         break;
928
929     case ps_idle_server:
930     case ps_wait_open:
931     case ps_disconnected_server:
932     case ps_wait_connect:
933         set_error( STATUS_PIPE_DISCONNECTED );
934         break;
935     }
936     release_object( server );
937 }
938
939 DECL_HANDLER(get_named_pipe_info)
940 {
941     struct pipe_server *server;
942     struct pipe_client *client = NULL;
943
944     server = get_pipe_server_obj( current->process, req->handle, FILE_READ_ATTRIBUTES );
945     if (!server)
946     {
947         clear_error();
948         client = (struct pipe_client *)get_handle_obj( current->process, req->handle,
949                                                        FILE_READ_ATTRIBUTES, &pipe_client_ops );
950         if (!client) return;
951         server = client->server;
952     }
953
954     reply->flags        = server->pipe->flags;
955     reply->maxinstances = server->pipe->maxinstances;
956     reply->instances    = server->pipe->instances;
957     reply->insize       = server->pipe->insize;
958     reply->outsize      = server->pipe->outsize;
959
960     if (client)
961         release_object(client);
962     else
963     {
964         reply->flags |= NAMED_PIPE_SERVER_END;
965         release_object(server);
966     }
967 }