Made IShellFolder::fnParseDisplayName return a relative pidl.
[wine] / server / pipe.c
1 /*
2  * Server-side pipe management
3  *
4  * Copyright (C) 1998 Alexandre Julliard
5  */
6
7 #include <assert.h>
8 #include <fcntl.h>
9 #include <string.h>
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <sys/errno.h>
13 #include <sys/stat.h>
14 #include <sys/time.h>
15 #include <sys/types.h>
16 #include <time.h>
17 #include <unistd.h>
18
19 #include "winerror.h"
20 #include "winbase.h"
21
22 #include "handle.h"
23 #include "thread.h"
24 #include "request.h"
25
26 enum side { READ_SIDE, WRITE_SIDE };
27
28 struct pipe
29 {
30     struct object       obj;         /* object header */
31     struct pipe        *other;       /* the pipe other end */
32     struct select_user  select;      /* select user */
33     enum side           side;        /* which side of the pipe is this */
34 };
35
36 static void pipe_dump( struct object *obj, int verbose );
37 static int pipe_add_queue( struct object *obj, struct wait_queue_entry *entry );
38 static void pipe_remove_queue( struct object *obj, struct wait_queue_entry *entry );
39 static int pipe_signaled( struct object *obj, struct thread *thread );
40 static int pipe_get_read_fd( struct object *obj );
41 static int pipe_get_write_fd( struct object *obj );
42 static int pipe_get_info( struct object *obj, struct get_file_info_request *req );
43 static void pipe_destroy( struct object *obj );
44
45 static const struct object_ops pipe_ops =
46 {
47     sizeof(struct pipe),
48     pipe_dump,
49     pipe_add_queue,
50     pipe_remove_queue,
51     pipe_signaled,
52     no_satisfied,
53     pipe_get_read_fd,
54     pipe_get_write_fd,
55     no_flush,
56     pipe_get_info,
57     pipe_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 )))
66     {
67         pipe->select.fd      = fd;
68         pipe->select.func    = default_select_event;
69         pipe->select.private = pipe;
70         pipe->other          = NULL;
71         pipe->side           = side;
72         register_select_user( &pipe->select );
73     }
74     return pipe;
75 }
76
77 static int create_pipe( struct object *obj[2] )
78 {
79     struct pipe *read_pipe;
80     struct pipe *write_pipe;
81     int fd[2];
82
83     if (pipe( fd ) == -1)
84     {
85         file_set_error();
86         return 0;
87     }
88     if ((read_pipe = create_pipe_side( fd[0], READ_SIDE )))
89     {
90         if ((write_pipe = create_pipe_side( fd[1], WRITE_SIDE )))
91         {
92             write_pipe->other = read_pipe;
93             read_pipe->other  = write_pipe;
94             obj[0] = &read_pipe->obj;
95             obj[1] = &write_pipe->obj;
96             return 1;
97         }
98         release_object( read_pipe );
99     }
100     close( fd[0] );
101     close( fd[1] );
102     return 0;
103 }
104
105 static void pipe_dump( struct object *obj, int verbose )
106 {
107     struct pipe *pipe = (struct pipe *)obj;
108     assert( obj->ops == &pipe_ops );
109     fprintf( stderr, "Pipe %s-side fd=%d\n",
110              (pipe->side == READ_SIDE) ? "read" : "write", pipe->select.fd );
111 }
112
113 static int pipe_add_queue( struct object *obj, struct wait_queue_entry *entry )
114 {
115     struct pipe *pipe = (struct pipe *)obj;
116     assert( obj->ops == &pipe_ops );
117     if (!obj->head)  /* first on the queue */
118         set_select_events( &pipe->select,
119                            (pipe->side == READ_SIDE) ? READ_EVENT : WRITE_EVENT );
120     add_queue( obj, entry );
121     return 1;
122 }
123
124 static void pipe_remove_queue( struct object *obj, struct wait_queue_entry *entry )
125 {
126     struct pipe *pipe = (struct pipe *)grab_object(obj);
127     assert( obj->ops == &pipe_ops );
128
129     remove_queue( obj, entry );
130     if (!obj->head)  /* last on the queue is gone */
131         set_select_events( &pipe->select, 0 );
132     release_object( obj );
133 }
134
135 static int pipe_signaled( struct object *obj, struct thread *thread )
136 {
137     int event;
138     struct pipe *pipe = (struct pipe *)obj;
139     assert( obj->ops == &pipe_ops );
140
141     event = (pipe->side == READ_SIDE) ? READ_EVENT : WRITE_EVENT;
142     if (check_select_events( &pipe->select, event ))
143     {
144         /* stop waiting on select() if we are signaled */
145         set_select_events( &pipe->select, 0 );
146         return 1;
147     }
148     else
149     {
150         /* restart waiting on select() if we are no longer signaled */
151         if (obj->head) set_select_events( &pipe->select, event );
152         return 0;
153     }
154 }
155
156 static int pipe_get_read_fd( struct object *obj )
157 {
158     struct pipe *pipe = (struct pipe *)obj;
159     assert( obj->ops == &pipe_ops );
160
161     if (!pipe->other)
162     {
163         set_error( ERROR_BROKEN_PIPE );
164         return -1;
165     }
166     if (pipe->side != READ_SIDE)  /* FIXME: should not be necessary */
167     {
168         set_error( ERROR_ACCESS_DENIED );
169         return -1;
170     }
171     return dup( pipe->select.fd );
172 }
173
174 static int pipe_get_write_fd( struct object *obj )
175 {
176     struct pipe *pipe = (struct pipe *)obj;
177     assert( obj->ops == &pipe_ops );
178
179     if (!pipe->other)
180     {
181         set_error( ERROR_BROKEN_PIPE );
182         return -1;
183     }
184     if (pipe->side != WRITE_SIDE)  /* FIXME: should not be necessary */
185     {
186         set_error( ERROR_ACCESS_DENIED );
187         return -1;
188     }
189     return dup( pipe->select.fd );
190 }
191
192 static int pipe_get_info( struct object *obj, struct get_file_info_request *req )
193 {
194     req->type        = FILE_TYPE_PIPE;
195     req->attr        = 0;
196     req->access_time = 0;
197     req->write_time  = 0;
198     req->size_high   = 0;
199     req->size_low    = 0;
200     req->links       = 0;
201     req->index_high  = 0;
202     req->index_low   = 0;
203     req->serial      = 0;
204     return 1;
205 }
206
207 static void pipe_destroy( struct object *obj )
208 {
209     struct pipe *pipe = (struct pipe *)obj;
210     assert( obj->ops == &pipe_ops );
211
212     if (pipe->other) pipe->other->other = NULL;
213     unregister_select_user( &pipe->select );
214     close( pipe->select.fd );
215 }
216
217 /* create an anonymous pipe */
218 DECL_HANDLER(create_pipe)
219 {
220     struct object *obj[2];
221     int hread = -1, hwrite = -1;
222
223     if (create_pipe( obj ))
224     {
225         hread = alloc_handle( current->process, obj[0],
226                               STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE|GENERIC_READ,
227                               req->inherit );
228         if (hread != -1)
229         {
230             hwrite = alloc_handle( current->process, obj[1],
231                                    STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE|GENERIC_WRITE,
232                                    req->inherit );
233             if (hwrite == -1)
234                 close_handle( current->process, hread );
235         }
236         release_object( obj[0] );
237         release_object( obj[1] );
238     }
239     req->handle_read  = hread;
240     req->handle_write = hwrite;
241 }