Fixed a bug that caused APCs to be "forgotten".
[wine] / server / pipe.c
1 /*
2  * Server-side pipe management
3  *
4  * Copyright (C) 1998 Alexandre Julliard
5  */
6
7 #include "config.h"
8
9 #include <assert.h>
10 #include <fcntl.h>
11 #include <string.h>
12 #include <stdio.h>
13 #include <stdlib.h>
14 #ifdef HAVE_SYS_ERRNO_H
15 #include <sys/errno.h>
16 #endif
17 #include <sys/time.h>
18 #include <sys/types.h>
19 #include <time.h>
20 #include <unistd.h>
21
22 #include "winbase.h"
23
24 #include "handle.h"
25 #include "thread.h"
26 #include "request.h"
27
28 enum side { READ_SIDE, WRITE_SIDE };
29
30 struct pipe
31 {
32     struct object       obj;         /* object header */
33     struct pipe        *other;       /* the pipe other end */
34     enum side           side;        /* which side of the pipe is this */
35 };
36
37 static void pipe_dump( struct object *obj, int verbose );
38 static int pipe_get_poll_events( struct object *obj );
39 static int pipe_get_fd( struct object *obj );
40 static int pipe_get_info( struct object *obj, struct get_file_info_reply *reply );
41 static void pipe_destroy( struct object *obj );
42
43 static const struct object_ops pipe_ops =
44 {
45     sizeof(struct pipe),          /* size */
46     pipe_dump,                    /* dump */
47     default_poll_add_queue,       /* add_queue */
48     default_poll_remove_queue,    /* remove_queue */
49     default_poll_signaled,        /* signaled */
50     no_satisfied,                 /* satisfied */
51     pipe_get_poll_events,         /* get_poll_events */
52     default_poll_event,           /* poll_event */
53     pipe_get_fd,                  /* get_fd */
54     no_flush,                     /* flush */
55     pipe_get_info,                /* get_file_info */
56     NULL,                         /* queue_async */
57     pipe_destroy                  /* destroy */
58 };
59
60
61 static struct pipe *create_pipe_side( int fd, int side )
62 {
63     struct pipe *pipe;
64
65     if ((pipe = alloc_object( &pipe_ops, fd )))
66     {
67         pipe->other  = NULL;
68         pipe->side   = side;
69     }
70     return pipe;
71 }
72
73 static int create_pipe( struct object *obj[2] )
74 {
75     struct pipe *read_pipe;
76     struct pipe *write_pipe;
77     int fd[2];
78
79     if (pipe( fd ) == -1)
80     {
81         file_set_error();
82         return 0;
83     }
84     if ((read_pipe = create_pipe_side( fd[0], READ_SIDE )))
85     {
86         if ((write_pipe = create_pipe_side( fd[1], WRITE_SIDE )))
87         {
88             write_pipe->other = read_pipe;
89             read_pipe->other  = write_pipe;
90             obj[0] = &read_pipe->obj;
91             obj[1] = &write_pipe->obj;
92             return 1;
93         }
94         release_object( read_pipe );
95     }
96     else close( fd[1] );
97     return 0;
98 }
99
100 static void pipe_dump( struct object *obj, int verbose )
101 {
102     struct pipe *pipe = (struct pipe *)obj;
103     assert( obj->ops == &pipe_ops );
104     fprintf( stderr, "Pipe %s-side fd=%d\n",
105              (pipe->side == READ_SIDE) ? "read" : "write", pipe->obj.fd );
106 }
107
108 static int pipe_get_poll_events( struct object *obj )
109 {
110     struct pipe *pipe = (struct pipe *)obj;
111     assert( obj->ops == &pipe_ops );
112     return (pipe->side == READ_SIDE) ? POLLIN : POLLOUT;
113 }
114
115 static int pipe_get_fd( struct object *obj )
116 {
117     struct pipe *pipe = (struct pipe *)obj;
118     assert( obj->ops == &pipe_ops );
119
120     if (!pipe->other)
121     {
122         set_error( STATUS_PIPE_BROKEN );
123         return -1;
124     }
125     return pipe->obj.fd;
126 }
127
128 static int pipe_get_info( struct object *obj, struct get_file_info_reply *reply )
129 {
130     if (reply)
131     {
132         reply->type        = FILE_TYPE_PIPE;
133         reply->attr        = 0;
134         reply->access_time = 0;
135         reply->write_time  = 0;
136         reply->size_high   = 0;
137         reply->size_low    = 0;
138         reply->links       = 0;
139         reply->index_high  = 0;
140         reply->index_low   = 0;
141         reply->serial      = 0;
142     }
143     return FD_TYPE_DEFAULT;
144 }
145
146 static void pipe_destroy( struct object *obj )
147 {
148     struct pipe *pipe = (struct pipe *)obj;
149     assert( obj->ops == &pipe_ops );
150
151     if (pipe->other) pipe->other->other = NULL;
152 }
153
154 /* create an anonymous pipe */
155 DECL_HANDLER(create_pipe)
156 {
157     struct object *obj[2];
158     handle_t hread = 0, hwrite = 0;
159
160     if (create_pipe( obj ))
161     {
162         hread = alloc_handle( current->process, obj[0],
163                               STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE|GENERIC_READ,
164                               req->inherit );
165         if (hread)
166         {
167             hwrite = alloc_handle( current->process, obj[1],
168                                    STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE|GENERIC_WRITE,
169                                    req->inherit );
170             if (!hwrite) close_handle( current->process, hread, NULL );
171         }
172         release_object( obj[0] );
173         release_object( obj[1] );
174     }
175     reply->handle_read  = hread;
176     reply->handle_write = hwrite;
177 }