Mike McCormack | 2ab6a77 | 2005-03-30 19:02:15 +0000 | [diff] [blame] | 1 | /* |
| 2 | * Server-side mailslot management |
| 3 | * |
| 4 | * Copyright (C) 1998 Alexandre Julliard |
| 5 | * Copyright (C) 2005 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 |
Jonathan Ernst | 360a3f9 | 2006-05-18 14:49:52 +0200 | [diff] [blame] | 19 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA |
Mike McCormack | 2ab6a77 | 2005-03-30 19:02:15 +0000 | [diff] [blame] | 20 | * |
| 21 | */ |
| 22 | |
| 23 | #include "config.h" |
| 24 | #include "wine/port.h" |
Ge van Geldorp | 1a1583a | 2005-11-28 17:32:54 +0100 | [diff] [blame] | 25 | #include "ntstatus.h" |
| 26 | #define WIN32_NO_STATUS |
Mike McCormack | 2ab6a77 | 2005-03-30 19:02:15 +0000 | [diff] [blame] | 27 | #include "wine/unicode.h" |
| 28 | |
| 29 | #include <assert.h> |
| 30 | #include <fcntl.h> |
| 31 | #include <string.h> |
| 32 | #include <stdarg.h> |
| 33 | #include <stdio.h> |
| 34 | #include <stdlib.h> |
| 35 | #include <sys/time.h> |
| 36 | #include <sys/types.h> |
| 37 | |
| 38 | #ifdef HAVE_SYS_IOCTL_H |
| 39 | #include <sys/ioctl.h> |
| 40 | #endif |
| 41 | #ifdef HAVE_SYS_SOCKET_H |
| 42 | #include <sys/socket.h> |
| 43 | #endif |
Robert Lunnon | 43e4139 | 2005-05-07 12:14:18 +0000 | [diff] [blame] | 44 | #ifdef HAVE_SYS_FILIO_H |
| 45 | #include <sys/filio.h> |
| 46 | #endif |
Mike McCormack | 2ab6a77 | 2005-03-30 19:02:15 +0000 | [diff] [blame] | 47 | #include "windef.h" |
Vitaliy Margolen | a996000 | 2005-10-27 18:30:37 +0000 | [diff] [blame] | 48 | #include "winternl.h" |
Mike McCormack | 2ab6a77 | 2005-03-30 19:02:15 +0000 | [diff] [blame] | 49 | |
| 50 | #include "file.h" |
| 51 | #include "handle.h" |
| 52 | #include "thread.h" |
| 53 | #include "request.h" |
| 54 | |
| 55 | struct mailslot |
| 56 | { |
| 57 | struct object obj; |
| 58 | struct fd *fd; |
Alexandre Julliard | 72ff2bf | 2007-04-12 20:19:28 +0200 | [diff] [blame] | 59 | int write_fd; |
Mike McCormack | 2ab6a77 | 2005-03-30 19:02:15 +0000 | [diff] [blame] | 60 | unsigned int max_msgsize; |
Alexandre Julliard | aaf477f | 2007-04-17 20:08:59 +0200 | [diff] [blame] | 61 | timeout_t read_timeout; |
Mike McCormack | 2ab6a77 | 2005-03-30 19:02:15 +0000 | [diff] [blame] | 62 | struct list writers; |
Mike McCormack | 2ab6a77 | 2005-03-30 19:02:15 +0000 | [diff] [blame] | 63 | }; |
| 64 | |
| 65 | /* mailslot functions */ |
| 66 | static void mailslot_dump( struct object*, int ); |
| 67 | static struct fd *mailslot_get_fd( struct object * ); |
Alexandre Julliard | a510a7e | 2005-12-12 16:46:17 +0100 | [diff] [blame] | 68 | static unsigned int mailslot_map_access( struct object *obj, unsigned int access ); |
Alexandre Julliard | 806bb49 | 2007-03-22 16:36:54 +0100 | [diff] [blame] | 69 | static struct object *mailslot_open_file( struct object *obj, unsigned int access, |
| 70 | unsigned int sharing, unsigned int options ); |
Mike McCormack | 2ab6a77 | 2005-03-30 19:02:15 +0000 | [diff] [blame] | 71 | static void mailslot_destroy( struct object * ); |
| 72 | |
| 73 | static const struct object_ops mailslot_ops = |
| 74 | { |
| 75 | sizeof(struct mailslot), /* size */ |
| 76 | mailslot_dump, /* dump */ |
Alexandre Julliard | 8382eb0 | 2007-12-05 18:16:42 +0100 | [diff] [blame] | 77 | no_get_type, /* get_type */ |
Alexandre Julliard | ba896e7 | 2007-04-04 19:39:29 +0200 | [diff] [blame] | 78 | add_queue, /* add_queue */ |
| 79 | remove_queue, /* remove_queue */ |
Mike McCormack | 2ab6a77 | 2005-03-30 19:02:15 +0000 | [diff] [blame] | 80 | default_fd_signaled, /* signaled */ |
| 81 | no_satisfied, /* satisfied */ |
Mike McCormack | f92fff6 | 2005-04-24 17:35:52 +0000 | [diff] [blame] | 82 | no_signal, /* signal */ |
Mike McCormack | 2ab6a77 | 2005-03-30 19:02:15 +0000 | [diff] [blame] | 83 | mailslot_get_fd, /* get_fd */ |
Alexandre Julliard | a510a7e | 2005-12-12 16:46:17 +0100 | [diff] [blame] | 84 | mailslot_map_access, /* map_access */ |
Rob Shearman | c1707d8 | 2007-10-03 13:10:37 +0100 | [diff] [blame] | 85 | default_get_sd, /* get_sd */ |
| 86 | default_set_sd, /* set_sd */ |
Vitaliy Margolen | baffcb9 | 2005-11-22 14:55:42 +0000 | [diff] [blame] | 87 | no_lookup_name, /* lookup_name */ |
Alexandre Julliard | 806bb49 | 2007-03-22 16:36:54 +0100 | [diff] [blame] | 88 | mailslot_open_file, /* open_file */ |
Alexandre Julliard | 715d78e | 2006-11-02 20:52:22 +0100 | [diff] [blame] | 89 | fd_close_handle, /* close_handle */ |
Mike McCormack | 2ab6a77 | 2005-03-30 19:02:15 +0000 | [diff] [blame] | 90 | mailslot_destroy /* destroy */ |
| 91 | }; |
| 92 | |
Alexandre Julliard | 7a9363a | 2007-04-10 22:26:23 +0200 | [diff] [blame] | 93 | static enum server_fd_type mailslot_get_fd_type( struct fd *fd ); |
Alexandre Julliard | 111610c | 2007-03-20 20:21:12 +0100 | [diff] [blame] | 94 | static void mailslot_queue_async( struct fd *fd, const async_data_t *data, int type, int count ); |
Mike McCormack | 2ab6a77 | 2005-03-30 19:02:15 +0000 | [diff] [blame] | 95 | |
| 96 | static const struct fd_ops mailslot_fd_ops = |
| 97 | { |
Robert Shearman | 37773dd | 2005-07-14 12:18:05 +0000 | [diff] [blame] | 98 | default_fd_get_poll_events, /* get_poll_events */ |
| 99 | default_poll_event, /* poll_event */ |
| 100 | no_flush, /* flush */ |
Alexandre Julliard | 7a9363a | 2007-04-10 22:26:23 +0200 | [diff] [blame] | 101 | mailslot_get_fd_type, /* get_fd_type */ |
Alexandre Julliard | 6357143 | 2007-04-16 14:45:03 +0200 | [diff] [blame] | 102 | default_fd_ioctl, /* ioctl */ |
Robert Shearman | 37773dd | 2005-07-14 12:18:05 +0000 | [diff] [blame] | 103 | mailslot_queue_async, /* queue_async */ |
Alexandre Julliard | 72bff2e | 2007-04-10 17:07:27 +0200 | [diff] [blame] | 104 | default_fd_reselect_async, /* reselect_async */ |
Robert Shearman | 37773dd | 2005-07-14 12:18:05 +0000 | [diff] [blame] | 105 | default_fd_cancel_async /* cancel_async */ |
Mike McCormack | 2ab6a77 | 2005-03-30 19:02:15 +0000 | [diff] [blame] | 106 | }; |
| 107 | |
Alexandre Julliard | a510a7e | 2005-12-12 16:46:17 +0100 | [diff] [blame] | 108 | |
Mike McCormack | 2ab6a77 | 2005-03-30 19:02:15 +0000 | [diff] [blame] | 109 | struct mail_writer |
| 110 | { |
| 111 | struct object obj; |
Alexandre Julliard | 72ff2bf | 2007-04-12 20:19:28 +0200 | [diff] [blame] | 112 | struct fd *fd; |
Mike McCormack | 2ab6a77 | 2005-03-30 19:02:15 +0000 | [diff] [blame] | 113 | struct mailslot *mailslot; |
| 114 | struct list entry; |
Alexandre Julliard | a510a7e | 2005-12-12 16:46:17 +0100 | [diff] [blame] | 115 | unsigned int access; |
| 116 | unsigned int sharing; |
Mike McCormack | 2ab6a77 | 2005-03-30 19:02:15 +0000 | [diff] [blame] | 117 | }; |
| 118 | |
| 119 | static void mail_writer_dump( struct object *obj, int verbose ); |
| 120 | static struct fd *mail_writer_get_fd( struct object *obj ); |
Alexandre Julliard | a510a7e | 2005-12-12 16:46:17 +0100 | [diff] [blame] | 121 | static unsigned int mail_writer_map_access( struct object *obj, unsigned int access ); |
Mike McCormack | 2ab6a77 | 2005-03-30 19:02:15 +0000 | [diff] [blame] | 122 | static void mail_writer_destroy( struct object *obj); |
| 123 | |
| 124 | static const struct object_ops mail_writer_ops = |
| 125 | { |
| 126 | sizeof(struct mail_writer), /* size */ |
| 127 | mail_writer_dump, /* dump */ |
Alexandre Julliard | 8382eb0 | 2007-12-05 18:16:42 +0100 | [diff] [blame] | 128 | no_get_type, /* get_type */ |
Mike McCormack | 2ab6a77 | 2005-03-30 19:02:15 +0000 | [diff] [blame] | 129 | no_add_queue, /* add_queue */ |
| 130 | NULL, /* remove_queue */ |
| 131 | NULL, /* signaled */ |
| 132 | NULL, /* satisfied */ |
Mike McCormack | f92fff6 | 2005-04-24 17:35:52 +0000 | [diff] [blame] | 133 | no_signal, /* signal */ |
Mike McCormack | 2ab6a77 | 2005-03-30 19:02:15 +0000 | [diff] [blame] | 134 | mail_writer_get_fd, /* get_fd */ |
Alexandre Julliard | a510a7e | 2005-12-12 16:46:17 +0100 | [diff] [blame] | 135 | mail_writer_map_access, /* map_access */ |
Rob Shearman | c1707d8 | 2007-10-03 13:10:37 +0100 | [diff] [blame] | 136 | default_get_sd, /* get_sd */ |
| 137 | default_set_sd, /* set_sd */ |
Vitaliy Margolen | baffcb9 | 2005-11-22 14:55:42 +0000 | [diff] [blame] | 138 | no_lookup_name, /* lookup_name */ |
Alexandre Julliard | 7e71c1d | 2007-03-22 11:44:29 +0100 | [diff] [blame] | 139 | no_open_file, /* open_file */ |
Alexandre Julliard | 715d78e | 2006-11-02 20:52:22 +0100 | [diff] [blame] | 140 | fd_close_handle, /* close_handle */ |
Mike McCormack | 2ab6a77 | 2005-03-30 19:02:15 +0000 | [diff] [blame] | 141 | mail_writer_destroy /* destroy */ |
| 142 | }; |
| 143 | |
Alexandre Julliard | 7a9363a | 2007-04-10 22:26:23 +0200 | [diff] [blame] | 144 | static enum server_fd_type mail_writer_get_fd_type( struct fd *fd ); |
Mike McCormack | 2ab6a77 | 2005-03-30 19:02:15 +0000 | [diff] [blame] | 145 | |
| 146 | static const struct fd_ops mail_writer_fd_ops = |
| 147 | { |
Alexandre Julliard | 72ff2bf | 2007-04-12 20:19:28 +0200 | [diff] [blame] | 148 | default_fd_get_poll_events, /* get_poll_events */ |
| 149 | default_poll_event, /* poll_event */ |
Mike McCormack | 2ab6a77 | 2005-03-30 19:02:15 +0000 | [diff] [blame] | 150 | no_flush, /* flush */ |
Alexandre Julliard | 7a9363a | 2007-04-10 22:26:23 +0200 | [diff] [blame] | 151 | mail_writer_get_fd_type, /* get_fd_type */ |
Alexandre Julliard | 6357143 | 2007-04-16 14:45:03 +0200 | [diff] [blame] | 152 | default_fd_ioctl, /* ioctl */ |
Alexandre Julliard | 72ff2bf | 2007-04-12 20:19:28 +0200 | [diff] [blame] | 153 | default_fd_queue_async, /* queue_async */ |
| 154 | default_fd_reselect_async, /* reselect_async */ |
| 155 | default_fd_cancel_async /* cancel_async */ |
Mike McCormack | 2ab6a77 | 2005-03-30 19:02:15 +0000 | [diff] [blame] | 156 | }; |
| 157 | |
Alexandre Julliard | a510a7e | 2005-12-12 16:46:17 +0100 | [diff] [blame] | 158 | |
| 159 | struct mailslot_device |
| 160 | { |
| 161 | struct object obj; /* object header */ |
| 162 | struct fd *fd; /* pseudo-fd for ioctls */ |
| 163 | struct namespace *mailslots; /* mailslot namespace */ |
| 164 | }; |
| 165 | |
Vitaliy Margolen | cf21d4d | 2005-12-05 13:30:26 +0100 | [diff] [blame] | 166 | static void mailslot_device_dump( struct object *obj, int verbose ); |
Alexandre Julliard | 8382eb0 | 2007-12-05 18:16:42 +0100 | [diff] [blame] | 167 | static struct object_type *mailslot_device_get_type( struct object *obj ); |
Alexandre Julliard | b0aa29e | 2005-12-12 14:39:27 +0100 | [diff] [blame] | 168 | static struct fd *mailslot_device_get_fd( struct object *obj ); |
Vitaliy Margolen | cf21d4d | 2005-12-05 13:30:26 +0100 | [diff] [blame] | 169 | static struct object *mailslot_device_lookup_name( struct object *obj, struct unicode_str *name, |
| 170 | unsigned int attr ); |
Alexandre Julliard | 94655c8 | 2007-03-22 11:52:40 +0100 | [diff] [blame] | 171 | static struct object *mailslot_device_open_file( struct object *obj, unsigned int access, |
| 172 | unsigned int sharing, unsigned int options ); |
Vitaliy Margolen | cf21d4d | 2005-12-05 13:30:26 +0100 | [diff] [blame] | 173 | static void mailslot_device_destroy( struct object *obj ); |
Alexandre Julliard | 7a9363a | 2007-04-10 22:26:23 +0200 | [diff] [blame] | 174 | static enum server_fd_type mailslot_device_get_fd_type( struct fd *fd ); |
Vitaliy Margolen | cf21d4d | 2005-12-05 13:30:26 +0100 | [diff] [blame] | 175 | |
| 176 | static const struct object_ops mailslot_device_ops = |
| 177 | { |
| 178 | sizeof(struct mailslot_device), /* size */ |
Alexandre Julliard | b0aa29e | 2005-12-12 14:39:27 +0100 | [diff] [blame] | 179 | mailslot_device_dump, /* dump */ |
Alexandre Julliard | 8382eb0 | 2007-12-05 18:16:42 +0100 | [diff] [blame] | 180 | mailslot_device_get_type, /* get_type */ |
Alexandre Julliard | b0aa29e | 2005-12-12 14:39:27 +0100 | [diff] [blame] | 181 | no_add_queue, /* add_queue */ |
| 182 | NULL, /* remove_queue */ |
| 183 | NULL, /* signaled */ |
| 184 | no_satisfied, /* satisfied */ |
| 185 | no_signal, /* signal */ |
| 186 | mailslot_device_get_fd, /* get_fd */ |
Alexandre Julliard | 28beba3 | 2005-12-12 14:57:40 +0100 | [diff] [blame] | 187 | no_map_access, /* map_access */ |
Rob Shearman | c1707d8 | 2007-10-03 13:10:37 +0100 | [diff] [blame] | 188 | default_get_sd, /* get_sd */ |
| 189 | default_set_sd, /* set_sd */ |
Alexandre Julliard | b0aa29e | 2005-12-12 14:39:27 +0100 | [diff] [blame] | 190 | mailslot_device_lookup_name, /* lookup_name */ |
Alexandre Julliard | 94655c8 | 2007-03-22 11:52:40 +0100 | [diff] [blame] | 191 | mailslot_device_open_file, /* open_file */ |
Alexandre Julliard | 715d78e | 2006-11-02 20:52:22 +0100 | [diff] [blame] | 192 | fd_close_handle, /* close_handle */ |
Alexandre Julliard | b0aa29e | 2005-12-12 14:39:27 +0100 | [diff] [blame] | 193 | mailslot_device_destroy /* destroy */ |
| 194 | }; |
| 195 | |
| 196 | static const struct fd_ops mailslot_device_fd_ops = |
| 197 | { |
Alexandre Julliard | 1acb930 | 2005-12-13 12:00:11 +0100 | [diff] [blame] | 198 | default_fd_get_poll_events, /* get_poll_events */ |
| 199 | default_poll_event, /* poll_event */ |
| 200 | no_flush, /* flush */ |
Alexandre Julliard | 7a9363a | 2007-04-10 22:26:23 +0200 | [diff] [blame] | 201 | mailslot_device_get_fd_type, /* get_fd_type */ |
Alexandre Julliard | 6357143 | 2007-04-16 14:45:03 +0200 | [diff] [blame] | 202 | default_fd_ioctl, /* ioctl */ |
Alexandre Julliard | 1acb930 | 2005-12-13 12:00:11 +0100 | [diff] [blame] | 203 | default_fd_queue_async, /* queue_async */ |
Alexandre Julliard | 72bff2e | 2007-04-10 17:07:27 +0200 | [diff] [blame] | 204 | default_fd_reselect_async, /* reselect_async */ |
Alexandre Julliard | 1acb930 | 2005-12-13 12:00:11 +0100 | [diff] [blame] | 205 | default_fd_cancel_async /* cancel_async */ |
Vitaliy Margolen | cf21d4d | 2005-12-05 13:30:26 +0100 | [diff] [blame] | 206 | }; |
| 207 | |
Mike McCormack | 2ab6a77 | 2005-03-30 19:02:15 +0000 | [diff] [blame] | 208 | static void mailslot_destroy( struct object *obj) |
| 209 | { |
| 210 | struct mailslot *mailslot = (struct mailslot *) obj; |
| 211 | |
| 212 | assert( mailslot->fd ); |
Mike McCormack | 2ab6a77 | 2005-03-30 19:02:15 +0000 | [diff] [blame] | 213 | |
Alexandre Julliard | 72ff2bf | 2007-04-12 20:19:28 +0200 | [diff] [blame] | 214 | if (mailslot->write_fd != -1) |
| 215 | { |
| 216 | shutdown( mailslot->write_fd, SHUT_RDWR ); |
| 217 | close( mailslot->write_fd ); |
| 218 | } |
Mike McCormack | 2ab6a77 | 2005-03-30 19:02:15 +0000 | [diff] [blame] | 219 | release_object( mailslot->fd ); |
Mike McCormack | 2ab6a77 | 2005-03-30 19:02:15 +0000 | [diff] [blame] | 220 | } |
| 221 | |
| 222 | static void mailslot_dump( struct object *obj, int verbose ) |
| 223 | { |
| 224 | struct mailslot *mailslot = (struct mailslot *) obj; |
| 225 | |
| 226 | assert( obj->ops == &mailslot_ops ); |
Alexandre Julliard | aaf477f | 2007-04-17 20:08:59 +0200 | [diff] [blame] | 227 | fprintf( stderr, "Mailslot max_msgsize=%d read_timeout=%s\n", |
| 228 | mailslot->max_msgsize, get_timeout_str(mailslot->read_timeout) ); |
Mike McCormack | 2ab6a77 | 2005-03-30 19:02:15 +0000 | [diff] [blame] | 229 | } |
| 230 | |
Alexandre Julliard | 7a9363a | 2007-04-10 22:26:23 +0200 | [diff] [blame] | 231 | static enum server_fd_type mailslot_get_fd_type( struct fd *fd ) |
Mike McCormack | 2ab6a77 | 2005-03-30 19:02:15 +0000 | [diff] [blame] | 232 | { |
Alexandre Julliard | 8930427 | 2006-11-20 14:14:04 +0100 | [diff] [blame] | 233 | return FD_TYPE_MAILSLOT; |
Mike McCormack | 2ab6a77 | 2005-03-30 19:02:15 +0000 | [diff] [blame] | 234 | } |
| 235 | |
| 236 | static struct fd *mailslot_get_fd( struct object *obj ) |
| 237 | { |
| 238 | struct mailslot *mailslot = (struct mailslot *) obj; |
| 239 | |
| 240 | return (struct fd *)grab_object( mailslot->fd ); |
| 241 | } |
| 242 | |
Alexandre Julliard | a510a7e | 2005-12-12 16:46:17 +0100 | [diff] [blame] | 243 | static unsigned int mailslot_map_access( struct object *obj, unsigned int access ) |
| 244 | { |
Alexandre Julliard | 02ed704 | 2007-04-02 20:24:55 +0200 | [diff] [blame] | 245 | /* mailslots can only be read */ |
Alexandre Julliard | a510a7e | 2005-12-12 16:46:17 +0100 | [diff] [blame] | 246 | if (access & GENERIC_READ) access |= FILE_GENERIC_READ; |
Alexandre Julliard | 02ed704 | 2007-04-02 20:24:55 +0200 | [diff] [blame] | 247 | if (access & GENERIC_ALL) access |= FILE_GENERIC_READ; |
Alexandre Julliard | a510a7e | 2005-12-12 16:46:17 +0100 | [diff] [blame] | 248 | return access & ~(GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE | GENERIC_ALL); |
| 249 | } |
| 250 | |
Alexandre Julliard | 806bb49 | 2007-03-22 16:36:54 +0100 | [diff] [blame] | 251 | static struct object *mailslot_open_file( struct object *obj, unsigned int access, |
| 252 | unsigned int sharing, unsigned int options ) |
| 253 | { |
| 254 | struct mailslot *mailslot = (struct mailslot *)obj; |
| 255 | struct mail_writer *writer; |
Alexandre Julliard | 72ff2bf | 2007-04-12 20:19:28 +0200 | [diff] [blame] | 256 | int unix_fd; |
Alexandre Julliard | 806bb49 | 2007-03-22 16:36:54 +0100 | [diff] [blame] | 257 | |
| 258 | if (!(sharing & FILE_SHARE_READ)) |
| 259 | { |
| 260 | set_error( STATUS_SHARING_VIOLATION ); |
| 261 | return NULL; |
| 262 | } |
| 263 | |
| 264 | if (!list_empty( &mailslot->writers )) |
| 265 | { |
| 266 | /* Readers and writers cannot be mixed. |
| 267 | * If there's more than one writer, all writers must open with FILE_SHARE_WRITE |
| 268 | */ |
| 269 | writer = LIST_ENTRY( list_head(&mailslot->writers), struct mail_writer, entry ); |
| 270 | |
| 271 | if (((access & (GENERIC_WRITE|FILE_WRITE_DATA)) || (writer->access & FILE_WRITE_DATA)) && |
| 272 | !((sharing & FILE_SHARE_WRITE) && (writer->sharing & FILE_SHARE_WRITE))) |
| 273 | { |
| 274 | set_error( STATUS_SHARING_VIOLATION ); |
| 275 | return NULL; |
| 276 | } |
| 277 | } |
| 278 | |
Alexandre Julliard | 72ff2bf | 2007-04-12 20:19:28 +0200 | [diff] [blame] | 279 | if ((unix_fd = dup( mailslot->write_fd )) == -1) |
| 280 | { |
| 281 | file_set_error(); |
| 282 | return NULL; |
| 283 | } |
| 284 | if (!(writer = alloc_object( &mail_writer_ops ))) |
| 285 | { |
| 286 | close( unix_fd ); |
| 287 | return NULL; |
| 288 | } |
Alexandre Julliard | 806bb49 | 2007-03-22 16:36:54 +0100 | [diff] [blame] | 289 | grab_object( mailslot ); |
| 290 | writer->mailslot = mailslot; |
| 291 | writer->access = mail_writer_map_access( &writer->obj, access ); |
| 292 | writer->sharing = sharing; |
Alexandre Julliard | 806bb49 | 2007-03-22 16:36:54 +0100 | [diff] [blame] | 293 | list_add_head( &mailslot->writers, &writer->entry ); |
Alexandre Julliard | 72ff2bf | 2007-04-12 20:19:28 +0200 | [diff] [blame] | 294 | |
| 295 | if (!(writer->fd = create_anonymous_fd( &mail_writer_fd_ops, unix_fd, &writer->obj, options ))) |
| 296 | { |
| 297 | release_object( writer ); |
| 298 | return NULL; |
| 299 | } |
Alexandre Julliard | 806bb49 | 2007-03-22 16:36:54 +0100 | [diff] [blame] | 300 | return &writer->obj; |
| 301 | } |
| 302 | |
Alexandre Julliard | 111610c | 2007-03-20 20:21:12 +0100 | [diff] [blame] | 303 | static void mailslot_queue_async( struct fd *fd, const async_data_t *data, int type, int count ) |
Mike McCormack | 2ab6a77 | 2005-03-30 19:02:15 +0000 | [diff] [blame] | 304 | { |
| 305 | struct mailslot *mailslot = get_fd_user( fd ); |
Alexandre Julliard | 0aae1ca | 2007-04-02 20:41:59 +0200 | [diff] [blame] | 306 | struct async *async; |
Mike McCormack | 2ab6a77 | 2005-03-30 19:02:15 +0000 | [diff] [blame] | 307 | |
| 308 | assert(mailslot->obj.ops == &mailslot_ops); |
| 309 | |
Alexandre Julliard | 0aae1ca | 2007-04-02 20:41:59 +0200 | [diff] [blame] | 310 | if ((async = fd_queue_async( fd, data, type, count ))) |
Alexandre Julliard | 40723f7 | 2006-07-26 11:47:42 +0200 | [diff] [blame] | 311 | { |
Alexandre Julliard | aaf477f | 2007-04-17 20:08:59 +0200 | [diff] [blame] | 312 | async_set_timeout( async, mailslot->read_timeout ? mailslot->read_timeout : -1, |
| 313 | STATUS_IO_TIMEOUT ); |
Alexandre Julliard | 0aae1ca | 2007-04-02 20:41:59 +0200 | [diff] [blame] | 314 | release_object( async ); |
| 315 | set_error( STATUS_PENDING ); |
Alexandre Julliard | 40723f7 | 2006-07-26 11:47:42 +0200 | [diff] [blame] | 316 | } |
Mike McCormack | 2ab6a77 | 2005-03-30 19:02:15 +0000 | [diff] [blame] | 317 | } |
| 318 | |
Vitaliy Margolen | cf21d4d | 2005-12-05 13:30:26 +0100 | [diff] [blame] | 319 | static void mailslot_device_dump( struct object *obj, int verbose ) |
| 320 | { |
| 321 | assert( obj->ops == &mailslot_device_ops ); |
| 322 | fprintf( stderr, "Mail slot device\n" ); |
| 323 | } |
| 324 | |
Alexandre Julliard | 8382eb0 | 2007-12-05 18:16:42 +0100 | [diff] [blame] | 325 | static struct object_type *mailslot_device_get_type( struct object *obj ) |
| 326 | { |
| 327 | static const WCHAR name[] = {'D','e','v','i','c','e'}; |
| 328 | static const struct unicode_str str = { name, sizeof(name) }; |
| 329 | return get_object_type( &str ); |
| 330 | } |
| 331 | |
Alexandre Julliard | b0aa29e | 2005-12-12 14:39:27 +0100 | [diff] [blame] | 332 | static struct fd *mailslot_device_get_fd( struct object *obj ) |
| 333 | { |
| 334 | struct mailslot_device *device = (struct mailslot_device *)obj; |
Alexandre Julliard | 5bcd088 | 2005-12-13 11:22:28 +0100 | [diff] [blame] | 335 | return (struct fd *)grab_object( device->fd ); |
Alexandre Julliard | b0aa29e | 2005-12-12 14:39:27 +0100 | [diff] [blame] | 336 | } |
| 337 | |
Vitaliy Margolen | cf21d4d | 2005-12-05 13:30:26 +0100 | [diff] [blame] | 338 | static struct object *mailslot_device_lookup_name( struct object *obj, struct unicode_str *name, |
| 339 | unsigned int attr ) |
| 340 | { |
| 341 | struct mailslot_device *device = (struct mailslot_device*)obj; |
| 342 | struct object *found; |
| 343 | |
| 344 | assert( obj->ops == &mailslot_device_ops ); |
| 345 | |
| 346 | if ((found = find_object( device->mailslots, name, attr | OBJ_CASE_INSENSITIVE ))) |
| 347 | name->len = 0; |
| 348 | |
| 349 | return found; |
| 350 | } |
| 351 | |
Alexandre Julliard | 94655c8 | 2007-03-22 11:52:40 +0100 | [diff] [blame] | 352 | static struct object *mailslot_device_open_file( struct object *obj, unsigned int access, |
| 353 | unsigned int sharing, unsigned int options ) |
| 354 | { |
| 355 | return grab_object( obj ); |
| 356 | } |
| 357 | |
Vitaliy Margolen | cf21d4d | 2005-12-05 13:30:26 +0100 | [diff] [blame] | 358 | static void mailslot_device_destroy( struct object *obj ) |
| 359 | { |
| 360 | struct mailslot_device *device = (struct mailslot_device*)obj; |
| 361 | assert( obj->ops == &mailslot_device_ops ); |
Alexandre Julliard | b0aa29e | 2005-12-12 14:39:27 +0100 | [diff] [blame] | 362 | if (device->fd) release_object( device->fd ); |
Michael Stefaniuc | 5ceccec | 2006-10-09 23:34:36 +0200 | [diff] [blame] | 363 | free( device->mailslots ); |
Vitaliy Margolen | cf21d4d | 2005-12-05 13:30:26 +0100 | [diff] [blame] | 364 | } |
| 365 | |
Alexandre Julliard | 7a9363a | 2007-04-10 22:26:23 +0200 | [diff] [blame] | 366 | static enum server_fd_type mailslot_device_get_fd_type( struct fd *fd ) |
Alexandre Julliard | 1acb930 | 2005-12-13 12:00:11 +0100 | [diff] [blame] | 367 | { |
Alexandre Julliard | 8930427 | 2006-11-20 14:14:04 +0100 | [diff] [blame] | 368 | return FD_TYPE_DEVICE; |
Alexandre Julliard | 1acb930 | 2005-12-13 12:00:11 +0100 | [diff] [blame] | 369 | } |
| 370 | |
Alexandre Julliard | b00fb17 | 2006-03-22 20:32:04 +0100 | [diff] [blame] | 371 | void create_mailslot_device( struct directory *root, const struct unicode_str *name ) |
Vitaliy Margolen | cf21d4d | 2005-12-05 13:30:26 +0100 | [diff] [blame] | 372 | { |
Vitaliy Margolen | cf21d4d | 2005-12-05 13:30:26 +0100 | [diff] [blame] | 373 | struct mailslot_device *dev; |
| 374 | |
Alexandre Julliard | d13095b | 2005-12-05 14:52:02 +0100 | [diff] [blame] | 375 | if ((dev = create_named_object_dir( root, name, 0, &mailslot_device_ops )) && |
Vitaliy Margolen | cf21d4d | 2005-12-05 13:30:26 +0100 | [diff] [blame] | 376 | get_error() != STATUS_OBJECT_NAME_EXISTS) |
| 377 | { |
Alexandre Julliard | b0aa29e | 2005-12-12 14:39:27 +0100 | [diff] [blame] | 378 | dev->mailslots = NULL; |
Alexandre Julliard | 017480d | 2007-05-03 16:07:30 +0200 | [diff] [blame] | 379 | if (!(dev->fd = alloc_pseudo_fd( &mailslot_device_fd_ops, &dev->obj, 0 )) || |
Alexandre Julliard | b0aa29e | 2005-12-12 14:39:27 +0100 | [diff] [blame] | 380 | !(dev->mailslots = create_namespace( 7 ))) |
Vitaliy Margolen | cf21d4d | 2005-12-05 13:30:26 +0100 | [diff] [blame] | 381 | { |
| 382 | release_object( dev ); |
| 383 | dev = NULL; |
| 384 | } |
| 385 | } |
Alexandre Julliard | b00fb17 | 2006-03-22 20:32:04 +0100 | [diff] [blame] | 386 | if (dev) make_object_static( &dev->obj ); |
Vitaliy Margolen | cf21d4d | 2005-12-05 13:30:26 +0100 | [diff] [blame] | 387 | } |
| 388 | |
| 389 | static struct mailslot *create_mailslot( struct directory *root, |
| 390 | const struct unicode_str *name, unsigned int attr, |
Alexandre Julliard | aaf477f | 2007-04-17 20:08:59 +0200 | [diff] [blame] | 391 | int max_msgsize, timeout_t read_timeout ) |
Mike McCormack | 2ab6a77 | 2005-03-30 19:02:15 +0000 | [diff] [blame] | 392 | { |
Vitaliy Margolen | cf21d4d | 2005-12-05 13:30:26 +0100 | [diff] [blame] | 393 | struct object *obj; |
| 394 | struct unicode_str new_name; |
| 395 | struct mailslot_device *dev; |
Mike McCormack | 2ab6a77 | 2005-03-30 19:02:15 +0000 | [diff] [blame] | 396 | struct mailslot *mailslot; |
| 397 | int fds[2]; |
Mike McCormack | 2ab6a77 | 2005-03-30 19:02:15 +0000 | [diff] [blame] | 398 | |
Vitaliy Margolen | cf21d4d | 2005-12-05 13:30:26 +0100 | [diff] [blame] | 399 | if (!name || !name->len) return alloc_object( &mailslot_ops ); |
| 400 | |
Alexandre Julliard | 928d28f | 2007-03-22 14:41:37 +0100 | [diff] [blame] | 401 | if (!(obj = find_object_dir( root, name, attr, &new_name ))) |
| 402 | { |
| 403 | set_error( STATUS_OBJECT_NAME_INVALID ); |
| 404 | return NULL; |
| 405 | } |
Vitaliy Margolen | cf21d4d | 2005-12-05 13:30:26 +0100 | [diff] [blame] | 406 | |
| 407 | if (!new_name.len) |
Mike McCormack | 2ab6a77 | 2005-03-30 19:02:15 +0000 | [diff] [blame] | 408 | { |
Vitaliy Margolen | cf21d4d | 2005-12-05 13:30:26 +0100 | [diff] [blame] | 409 | if (attr & OBJ_OPENIF && obj->ops == &mailslot_ops) |
| 410 | /* it already exists - there can only be one mailslot to read from */ |
| 411 | set_error( STATUS_OBJECT_NAME_EXISTS ); |
| 412 | else if (attr & OBJ_OPENIF) |
| 413 | set_error( STATUS_OBJECT_TYPE_MISMATCH ); |
| 414 | else |
| 415 | set_error( STATUS_OBJECT_NAME_COLLISION ); |
| 416 | release_object( obj ); |
Mike McCormack | 2ab6a77 | 2005-03-30 19:02:15 +0000 | [diff] [blame] | 417 | return NULL; |
| 418 | } |
| 419 | |
Vitaliy Margolen | cf21d4d | 2005-12-05 13:30:26 +0100 | [diff] [blame] | 420 | if (obj->ops != &mailslot_device_ops) |
Mike McCormack | 2ab6a77 | 2005-03-30 19:02:15 +0000 | [diff] [blame] | 421 | { |
Alexandre Julliard | 928d28f | 2007-03-22 14:41:37 +0100 | [diff] [blame] | 422 | set_error( STATUS_OBJECT_NAME_INVALID ); |
Vitaliy Margolen | cf21d4d | 2005-12-05 13:30:26 +0100 | [diff] [blame] | 423 | release_object( obj ); |
Mike McCormack | 2ab6a77 | 2005-03-30 19:02:15 +0000 | [diff] [blame] | 424 | return NULL; |
| 425 | } |
| 426 | |
Vitaliy Margolen | cf21d4d | 2005-12-05 13:30:26 +0100 | [diff] [blame] | 427 | dev = (struct mailslot_device *)obj; |
| 428 | mailslot = create_object( dev->mailslots, &mailslot_ops, &new_name, NULL ); |
| 429 | release_object( dev ); |
| 430 | |
| 431 | if (!mailslot) return NULL; |
| 432 | |
Mike McCormack | 2ab6a77 | 2005-03-30 19:02:15 +0000 | [diff] [blame] | 433 | mailslot->fd = NULL; |
Alexandre Julliard | 72ff2bf | 2007-04-12 20:19:28 +0200 | [diff] [blame] | 434 | mailslot->write_fd = -1; |
Mike McCormack | 2ab6a77 | 2005-03-30 19:02:15 +0000 | [diff] [blame] | 435 | mailslot->max_msgsize = max_msgsize; |
| 436 | mailslot->read_timeout = read_timeout; |
| 437 | list_init( &mailslot->writers ); |
Mike McCormack | 2ab6a77 | 2005-03-30 19:02:15 +0000 | [diff] [blame] | 438 | |
Robert Shearman | 3795709 | 2005-06-10 19:54:46 +0000 | [diff] [blame] | 439 | if (!socketpair( PF_UNIX, SOCK_DGRAM, 0, fds )) |
Mike McCormack | 2ab6a77 | 2005-03-30 19:02:15 +0000 | [diff] [blame] | 440 | { |
| 441 | fcntl( fds[0], F_SETFL, O_NONBLOCK ); |
| 442 | fcntl( fds[1], F_SETFL, O_NONBLOCK ); |
Alexandre Julliard | bc426ab | 2007-04-10 21:30:37 +0200 | [diff] [blame] | 443 | shutdown( fds[0], SHUT_RD ); |
Alexandre Julliard | 72ff2bf | 2007-04-12 20:19:28 +0200 | [diff] [blame] | 444 | mailslot->write_fd = fds[0]; |
Alexandre Julliard | f85437c | 2007-04-10 22:25:07 +0200 | [diff] [blame] | 445 | mailslot->fd = create_anonymous_fd( &mailslot_fd_ops, fds[1], &mailslot->obj, |
| 446 | FILE_SYNCHRONOUS_IO_NONALERT ); |
Alexandre Julliard | 72ff2bf | 2007-04-12 20:19:28 +0200 | [diff] [blame] | 447 | if (mailslot->fd) return mailslot; |
Mike McCormack | 2ab6a77 | 2005-03-30 19:02:15 +0000 | [diff] [blame] | 448 | } |
| 449 | else file_set_error(); |
| 450 | |
| 451 | release_object( mailslot ); |
| 452 | return NULL; |
| 453 | } |
| 454 | |
Mike McCormack | 2ab6a77 | 2005-03-30 19:02:15 +0000 | [diff] [blame] | 455 | static void mail_writer_dump( struct object *obj, int verbose ) |
| 456 | { |
| 457 | fprintf( stderr, "Mailslot writer\n" ); |
| 458 | } |
| 459 | |
| 460 | static void mail_writer_destroy( struct object *obj) |
| 461 | { |
| 462 | struct mail_writer *writer = (struct mail_writer *) obj; |
| 463 | |
Alexandre Julliard | 72ff2bf | 2007-04-12 20:19:28 +0200 | [diff] [blame] | 464 | if (writer->fd) release_object( writer->fd ); |
Mike McCormack | 2ab6a77 | 2005-03-30 19:02:15 +0000 | [diff] [blame] | 465 | list_remove( &writer->entry ); |
| 466 | release_object( writer->mailslot ); |
| 467 | } |
| 468 | |
Alexandre Julliard | 7a9363a | 2007-04-10 22:26:23 +0200 | [diff] [blame] | 469 | static enum server_fd_type mail_writer_get_fd_type( struct fd *fd ) |
Mike McCormack | 2ab6a77 | 2005-03-30 19:02:15 +0000 | [diff] [blame] | 470 | { |
Alexandre Julliard | 8930427 | 2006-11-20 14:14:04 +0100 | [diff] [blame] | 471 | return FD_TYPE_MAILSLOT; |
Mike McCormack | 2ab6a77 | 2005-03-30 19:02:15 +0000 | [diff] [blame] | 472 | } |
| 473 | |
| 474 | static struct fd *mail_writer_get_fd( struct object *obj ) |
| 475 | { |
| 476 | struct mail_writer *writer = (struct mail_writer *) obj; |
Alexandre Julliard | 72ff2bf | 2007-04-12 20:19:28 +0200 | [diff] [blame] | 477 | return (struct fd *)grab_object( writer->fd ); |
Mike McCormack | 2ab6a77 | 2005-03-30 19:02:15 +0000 | [diff] [blame] | 478 | } |
| 479 | |
Alexandre Julliard | a510a7e | 2005-12-12 16:46:17 +0100 | [diff] [blame] | 480 | static unsigned int mail_writer_map_access( struct object *obj, unsigned int access ) |
| 481 | { |
Alexandre Julliard | 806bb49 | 2007-03-22 16:36:54 +0100 | [diff] [blame] | 482 | /* mailslot writers can only get write access */ |
Alexandre Julliard | a510a7e | 2005-12-12 16:46:17 +0100 | [diff] [blame] | 483 | if (access & GENERIC_WRITE) access |= FILE_GENERIC_WRITE; |
Alexandre Julliard | 806bb49 | 2007-03-22 16:36:54 +0100 | [diff] [blame] | 484 | if (access & GENERIC_ALL) access |= FILE_GENERIC_WRITE; |
Alexandre Julliard | a510a7e | 2005-12-12 16:46:17 +0100 | [diff] [blame] | 485 | return access & ~(GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE | GENERIC_ALL); |
| 486 | } |
| 487 | |
Mike McCormack | 2ab6a77 | 2005-03-30 19:02:15 +0000 | [diff] [blame] | 488 | static struct mailslot *get_mailslot_obj( struct process *process, obj_handle_t handle, |
| 489 | unsigned int access ) |
| 490 | { |
Vitaliy Margolen | cf21d4d | 2005-12-05 13:30:26 +0100 | [diff] [blame] | 491 | return (struct mailslot *)get_handle_obj( process, handle, access, &mailslot_ops ); |
Mike McCormack | 2ab6a77 | 2005-03-30 19:02:15 +0000 | [diff] [blame] | 492 | } |
| 493 | |
| 494 | |
| 495 | /* create a mailslot */ |
| 496 | DECL_HANDLER(create_mailslot) |
| 497 | { |
| 498 | struct mailslot *mailslot; |
Alexandre Julliard | ead9b06 | 2005-11-18 16:31:18 +0000 | [diff] [blame] | 499 | struct unicode_str name; |
Vitaliy Margolen | cf21d4d | 2005-12-05 13:30:26 +0100 | [diff] [blame] | 500 | struct directory *root = NULL; |
Mike McCormack | 2ab6a77 | 2005-03-30 19:02:15 +0000 | [diff] [blame] | 501 | |
| 502 | reply->handle = 0; |
Alexandre Julliard | ead9b06 | 2005-11-18 16:31:18 +0000 | [diff] [blame] | 503 | get_req_unicode_str( &name ); |
Vitaliy Margolen | cf21d4d | 2005-12-05 13:30:26 +0100 | [diff] [blame] | 504 | if (req->rootdir && !(root = get_directory_obj( current->process, req->rootdir, 0 ))) |
| 505 | return; |
| 506 | |
| 507 | if ((mailslot = create_mailslot( root, &name, req->attributes, req->max_msgsize, |
| 508 | req->read_timeout ))) |
Mike McCormack | 2ab6a77 | 2005-03-30 19:02:15 +0000 | [diff] [blame] | 509 | { |
Alexandre Julliard | 24560e7 | 2005-12-09 13:58:25 +0100 | [diff] [blame] | 510 | reply->handle = alloc_handle( current->process, mailslot, req->access, req->attributes ); |
Mike McCormack | 2ab6a77 | 2005-03-30 19:02:15 +0000 | [diff] [blame] | 511 | release_object( mailslot ); |
| 512 | } |
Vitaliy Margolen | cf21d4d | 2005-12-05 13:30:26 +0100 | [diff] [blame] | 513 | |
| 514 | if (root) release_object( root ); |
Mike McCormack | 2ab6a77 | 2005-03-30 19:02:15 +0000 | [diff] [blame] | 515 | } |
| 516 | |
| 517 | |
Mike McCormack | 2ab6a77 | 2005-03-30 19:02:15 +0000 | [diff] [blame] | 518 | /* set mailslot information */ |
| 519 | DECL_HANDLER(set_mailslot_info) |
| 520 | { |
| 521 | struct mailslot *mailslot = get_mailslot_obj( current->process, req->handle, 0 ); |
| 522 | |
Robert Shearman | 3795709 | 2005-06-10 19:54:46 +0000 | [diff] [blame] | 523 | if (mailslot) |
Mike McCormack | 2ab6a77 | 2005-03-30 19:02:15 +0000 | [diff] [blame] | 524 | { |
Robert Shearman | 3795709 | 2005-06-10 19:54:46 +0000 | [diff] [blame] | 525 | if (req->flags & MAILSLOT_SET_READ_TIMEOUT) |
Mike McCormack | 2ab6a77 | 2005-03-30 19:02:15 +0000 | [diff] [blame] | 526 | mailslot->read_timeout = req->read_timeout; |
| 527 | reply->max_msgsize = mailslot->max_msgsize; |
| 528 | reply->read_timeout = mailslot->read_timeout; |
Mike McCormack | 2ab6a77 | 2005-03-30 19:02:15 +0000 | [diff] [blame] | 529 | release_object( mailslot ); |
| 530 | } |
| 531 | } |