mailslot.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545
  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
  19. * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  20. *
  21. */
  22. #include "config.h"
  23. #include "wine/port.h"
  24. #include "ntstatus.h"
  25. #define WIN32_NO_STATUS
  26. #include <assert.h>
  27. #include <fcntl.h>
  28. #include <string.h>
  29. #include <stdarg.h>
  30. #include <stdio.h>
  31. #include <stdlib.h>
  32. #include <sys/time.h>
  33. #include <sys/types.h>
  34. #ifdef HAVE_SYS_IOCTL_H
  35. #include <sys/ioctl.h>
  36. #endif
  37. #ifdef HAVE_SYS_SOCKET_H
  38. #include <sys/socket.h>
  39. #endif
  40. #ifdef HAVE_SYS_FILIO_H
  41. #include <sys/filio.h>
  42. #endif
  43. #include "windef.h"
  44. #include "winternl.h"
  45. #include "file.h"
  46. #include "handle.h"
  47. #include "thread.h"
  48. #include "request.h"
  49. struct mailslot
  50. {
  51. struct object obj;
  52. struct fd *fd;
  53. int write_fd;
  54. unsigned int max_msgsize;
  55. timeout_t read_timeout;
  56. struct list writers;
  57. };
  58. /* mailslot functions */
  59. static void mailslot_dump( struct object*, int );
  60. static struct fd *mailslot_get_fd( struct object * );
  61. static unsigned int mailslot_map_access( struct object *obj, unsigned int access );
  62. static int mailslot_link_name( struct object *obj, struct object_name *name, struct object *parent );
  63. static struct object *mailslot_open_file( struct object *obj, unsigned int access,
  64. unsigned int sharing, unsigned int options );
  65. static void mailslot_destroy( struct object * );
  66. static const struct object_ops mailslot_ops =
  67. {
  68. sizeof(struct mailslot), /* size */
  69. mailslot_dump, /* dump */
  70. file_get_type, /* get_type */
  71. add_queue, /* add_queue */
  72. remove_queue, /* remove_queue */
  73. default_fd_signaled, /* signaled */
  74. NULL, /* get_esync_fd */
  75. no_satisfied, /* satisfied */
  76. no_signal, /* signal */
  77. mailslot_get_fd, /* get_fd */
  78. mailslot_map_access, /* map_access */
  79. default_get_sd, /* get_sd */
  80. default_set_sd, /* set_sd */
  81. no_lookup_name, /* lookup_name */
  82. mailslot_link_name, /* link_name */
  83. default_unlink_name, /* unlink_name */
  84. mailslot_open_file, /* open_file */
  85. no_kernel_obj_list, /* get_kernel_obj_list */
  86. no_alloc_handle, /* alloc_handle */
  87. fd_close_handle, /* close_handle */
  88. mailslot_destroy /* destroy */
  89. };
  90. static enum server_fd_type mailslot_get_fd_type( struct fd *fd );
  91. static void mailslot_queue_async( struct fd *fd, struct async *async, int type, int count );
  92. static const struct fd_ops mailslot_fd_ops =
  93. {
  94. default_fd_get_poll_events, /* get_poll_events */
  95. default_poll_event, /* poll_event */
  96. mailslot_get_fd_type, /* get_fd_type */
  97. no_fd_read, /* read */
  98. no_fd_write, /* write */
  99. no_fd_flush, /* flush */
  100. default_fd_get_file_info, /* get_file_info */
  101. no_fd_get_volume_info, /* get_volume_info */
  102. default_fd_ioctl, /* ioctl */
  103. mailslot_queue_async, /* queue_async */
  104. default_fd_reselect_async /* reselect_async */
  105. };
  106. struct mail_writer
  107. {
  108. struct object obj;
  109. struct fd *fd;
  110. struct mailslot *mailslot;
  111. struct list entry;
  112. unsigned int access;
  113. unsigned int sharing;
  114. };
  115. static void mail_writer_dump( struct object *obj, int verbose );
  116. static struct fd *mail_writer_get_fd( struct object *obj );
  117. static unsigned int mail_writer_map_access( struct object *obj, unsigned int access );
  118. static void mail_writer_destroy( struct object *obj);
  119. static const struct object_ops mail_writer_ops =
  120. {
  121. sizeof(struct mail_writer), /* size */
  122. mail_writer_dump, /* dump */
  123. file_get_type, /* get_type */
  124. no_add_queue, /* add_queue */
  125. NULL, /* remove_queue */
  126. NULL, /* signaled */
  127. NULL, /* get_esync_fd */
  128. NULL, /* satisfied */
  129. no_signal, /* signal */
  130. mail_writer_get_fd, /* get_fd */
  131. mail_writer_map_access, /* map_access */
  132. default_get_sd, /* get_sd */
  133. default_set_sd, /* set_sd */
  134. no_lookup_name, /* lookup_name */
  135. no_link_name, /* link_name */
  136. NULL, /* unlink_name */
  137. no_open_file, /* open_file */
  138. no_kernel_obj_list, /* get_kernel_obj_list */
  139. no_alloc_handle, /* alloc_handle */
  140. fd_close_handle, /* close_handle */
  141. mail_writer_destroy /* destroy */
  142. };
  143. static enum server_fd_type mail_writer_get_fd_type( struct fd *fd );
  144. static const struct fd_ops mail_writer_fd_ops =
  145. {
  146. default_fd_get_poll_events, /* get_poll_events */
  147. default_poll_event, /* poll_event */
  148. mail_writer_get_fd_type, /* get_fd_type */
  149. no_fd_read, /* read */
  150. no_fd_write, /* write */
  151. no_fd_flush, /* flush */
  152. default_fd_get_file_info, /* get_file_info */
  153. no_fd_get_volume_info, /* get_volume_info */
  154. default_fd_ioctl, /* ioctl */
  155. default_fd_queue_async, /* queue_async */
  156. default_fd_reselect_async /* reselect_async */
  157. };
  158. struct mailslot_device
  159. {
  160. struct object obj; /* object header */
  161. struct fd *fd; /* pseudo-fd for ioctls */
  162. struct namespace *mailslots; /* mailslot namespace */
  163. };
  164. static void mailslot_device_dump( struct object *obj, int verbose );
  165. static struct object_type *mailslot_device_get_type( struct object *obj );
  166. static struct fd *mailslot_device_get_fd( struct object *obj );
  167. static struct object *mailslot_device_lookup_name( struct object *obj, struct unicode_str *name,
  168. unsigned int attr );
  169. static struct object *mailslot_device_open_file( struct object *obj, unsigned int access,
  170. unsigned int sharing, unsigned int options );
  171. static void mailslot_device_destroy( struct object *obj );
  172. static enum server_fd_type mailslot_device_get_fd_type( struct fd *fd );
  173. static const struct object_ops mailslot_device_ops =
  174. {
  175. sizeof(struct mailslot_device), /* size */
  176. mailslot_device_dump, /* dump */
  177. mailslot_device_get_type, /* get_type */
  178. no_add_queue, /* add_queue */
  179. NULL, /* remove_queue */
  180. NULL, /* signaled */
  181. NULL, /* get_esync_fd */
  182. no_satisfied, /* satisfied */
  183. no_signal, /* signal */
  184. mailslot_device_get_fd, /* get_fd */
  185. no_map_access, /* map_access */
  186. default_get_sd, /* get_sd */
  187. default_set_sd, /* set_sd */
  188. mailslot_device_lookup_name, /* lookup_name */
  189. directory_link_name, /* link_name */
  190. default_unlink_name, /* unlink_name */
  191. mailslot_device_open_file, /* open_file */
  192. no_kernel_obj_list, /* get_kernel_obj_list */
  193. no_alloc_handle, /* alloc_handle */
  194. fd_close_handle, /* close_handle */
  195. mailslot_device_destroy /* destroy */
  196. };
  197. static const struct fd_ops mailslot_device_fd_ops =
  198. {
  199. default_fd_get_poll_events, /* get_poll_events */
  200. default_poll_event, /* poll_event */
  201. mailslot_device_get_fd_type, /* get_fd_type */
  202. no_fd_read, /* read */
  203. no_fd_write, /* write */
  204. no_fd_flush, /* flush */
  205. default_fd_get_file_info, /* get_file_info */
  206. no_fd_get_volume_info, /* get_volume_info */
  207. default_fd_ioctl, /* ioctl */
  208. default_fd_queue_async, /* queue_async */
  209. default_fd_reselect_async /* reselect_async */
  210. };
  211. static void mailslot_destroy( struct object *obj)
  212. {
  213. struct mailslot *mailslot = (struct mailslot *) obj;
  214. assert( mailslot->fd );
  215. if (mailslot->write_fd != -1)
  216. {
  217. shutdown( mailslot->write_fd, SHUT_RDWR );
  218. close( mailslot->write_fd );
  219. }
  220. release_object( mailslot->fd );
  221. }
  222. static void mailslot_dump( struct object *obj, int verbose )
  223. {
  224. struct mailslot *mailslot = (struct mailslot *) obj;
  225. assert( obj->ops == &mailslot_ops );
  226. fprintf( stderr, "Mailslot max_msgsize=%d read_timeout=%s\n",
  227. mailslot->max_msgsize, get_timeout_str(mailslot->read_timeout) );
  228. }
  229. static enum server_fd_type mailslot_get_fd_type( struct fd *fd )
  230. {
  231. return FD_TYPE_MAILSLOT;
  232. }
  233. static struct fd *mailslot_get_fd( struct object *obj )
  234. {
  235. struct mailslot *mailslot = (struct mailslot *) obj;
  236. return (struct fd *)grab_object( mailslot->fd );
  237. }
  238. static unsigned int mailslot_map_access( struct object *obj, unsigned int access )
  239. {
  240. /* mailslots can only be read */
  241. if (access & GENERIC_READ) access |= FILE_GENERIC_READ;
  242. if (access & GENERIC_ALL) access |= FILE_GENERIC_READ;
  243. return access & ~(GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE | GENERIC_ALL);
  244. }
  245. static int mailslot_link_name( struct object *obj, struct object_name *name, struct object *parent )
  246. {
  247. struct mailslot_device *dev = (struct mailslot_device *)parent;
  248. if (parent->ops != &mailslot_device_ops)
  249. {
  250. set_error( STATUS_OBJECT_NAME_INVALID );
  251. return 0;
  252. }
  253. namespace_add( dev->mailslots, name );
  254. name->parent = grab_object( parent );
  255. return 1;
  256. }
  257. static struct object *mailslot_open_file( struct object *obj, unsigned int access,
  258. unsigned int sharing, unsigned int options )
  259. {
  260. struct mailslot *mailslot = (struct mailslot *)obj;
  261. struct mail_writer *writer;
  262. int unix_fd;
  263. if (!(sharing & FILE_SHARE_READ))
  264. {
  265. set_error( STATUS_SHARING_VIOLATION );
  266. return NULL;
  267. }
  268. if (!list_empty( &mailslot->writers ))
  269. {
  270. /* Readers and writers cannot be mixed.
  271. * If there's more than one writer, all writers must open with FILE_SHARE_WRITE
  272. */
  273. writer = LIST_ENTRY( list_head(&mailslot->writers), struct mail_writer, entry );
  274. if (((access & (GENERIC_WRITE|FILE_WRITE_DATA)) || (writer->access & FILE_WRITE_DATA)) &&
  275. !((sharing & FILE_SHARE_WRITE) && (writer->sharing & FILE_SHARE_WRITE)))
  276. {
  277. set_error( STATUS_SHARING_VIOLATION );
  278. return NULL;
  279. }
  280. }
  281. if ((unix_fd = dup( mailslot->write_fd )) == -1)
  282. {
  283. file_set_error();
  284. return NULL;
  285. }
  286. if (!(writer = alloc_object( &mail_writer_ops )))
  287. {
  288. close( unix_fd );
  289. return NULL;
  290. }
  291. grab_object( mailslot );
  292. writer->mailslot = mailslot;
  293. writer->access = mail_writer_map_access( &writer->obj, access );
  294. writer->sharing = sharing;
  295. list_add_head( &mailslot->writers, &writer->entry );
  296. if (!(writer->fd = create_anonymous_fd( &mail_writer_fd_ops, unix_fd, &writer->obj, options )))
  297. {
  298. release_object( writer );
  299. return NULL;
  300. }
  301. allow_fd_caching( writer->fd );
  302. return &writer->obj;
  303. }
  304. static void mailslot_queue_async( struct fd *fd, struct async *async, int type, int count )
  305. {
  306. struct mailslot *mailslot = get_fd_user( fd );
  307. assert(mailslot->obj.ops == &mailslot_ops);
  308. fd_queue_async( fd, async, type );
  309. async_set_timeout( async, mailslot->read_timeout ? mailslot->read_timeout : -1,
  310. STATUS_IO_TIMEOUT );
  311. set_error( STATUS_PENDING );
  312. }
  313. static void mailslot_device_dump( struct object *obj, int verbose )
  314. {
  315. fputs( "Mailslot device\n", stderr );
  316. }
  317. static struct object_type *mailslot_device_get_type( struct object *obj )
  318. {
  319. const struct unicode_str str = { type_Device, sizeof(type_Device) };
  320. return get_object_type( &str );
  321. }
  322. static struct fd *mailslot_device_get_fd( struct object *obj )
  323. {
  324. struct mailslot_device *device = (struct mailslot_device *)obj;
  325. return (struct fd *)grab_object( device->fd );
  326. }
  327. static struct object *mailslot_device_lookup_name( struct object *obj, struct unicode_str *name,
  328. unsigned int attr )
  329. {
  330. struct mailslot_device *device = (struct mailslot_device*)obj;
  331. struct object *found;
  332. assert( obj->ops == &mailslot_device_ops );
  333. if (!name) return NULL; /* open the device itself */
  334. if ((found = find_object( device->mailslots, name, attr | OBJ_CASE_INSENSITIVE )))
  335. name->len = 0;
  336. return found;
  337. }
  338. static struct object *mailslot_device_open_file( struct object *obj, unsigned int access,
  339. unsigned int sharing, unsigned int options )
  340. {
  341. return grab_object( obj );
  342. }
  343. static void mailslot_device_destroy( struct object *obj )
  344. {
  345. struct mailslot_device *device = (struct mailslot_device*)obj;
  346. assert( obj->ops == &mailslot_device_ops );
  347. if (device->fd) release_object( device->fd );
  348. free( device->mailslots );
  349. }
  350. static enum server_fd_type mailslot_device_get_fd_type( struct fd *fd )
  351. {
  352. return FD_TYPE_DEVICE;
  353. }
  354. struct object *create_mailslot_device( struct object *root, const struct unicode_str *name )
  355. {
  356. struct mailslot_device *dev;
  357. if ((dev = create_named_object( root, &mailslot_device_ops, name, 0, NULL )) &&
  358. get_error() != STATUS_OBJECT_NAME_EXISTS)
  359. {
  360. dev->mailslots = NULL;
  361. if (!(dev->fd = alloc_pseudo_fd( &mailslot_device_fd_ops, &dev->obj, 0 )) ||
  362. !(dev->mailslots = create_namespace( 7 )))
  363. {
  364. release_object( dev );
  365. dev = NULL;
  366. }
  367. }
  368. return &dev->obj;
  369. }
  370. static struct mailslot *create_mailslot( struct object *root,
  371. const struct unicode_str *name, unsigned int attr,
  372. int max_msgsize, timeout_t read_timeout,
  373. const struct security_descriptor *sd )
  374. {
  375. struct mailslot *mailslot;
  376. int fds[2];
  377. if (!(mailslot = create_named_object( root, &mailslot_ops, name, attr, sd ))) return NULL;
  378. mailslot->fd = NULL;
  379. mailslot->write_fd = -1;
  380. mailslot->max_msgsize = max_msgsize;
  381. mailslot->read_timeout = read_timeout;
  382. list_init( &mailslot->writers );
  383. if (!socketpair( PF_UNIX, SOCK_DGRAM, 0, fds ))
  384. {
  385. fcntl( fds[0], F_SETFL, O_NONBLOCK );
  386. fcntl( fds[1], F_SETFL, O_NONBLOCK );
  387. shutdown( fds[0], SHUT_RD );
  388. mailslot->write_fd = fds[0];
  389. if ((mailslot->fd = create_anonymous_fd( &mailslot_fd_ops, fds[1], &mailslot->obj,
  390. FILE_SYNCHRONOUS_IO_NONALERT )))
  391. {
  392. allow_fd_caching( mailslot->fd );
  393. return mailslot;
  394. }
  395. }
  396. else file_set_error();
  397. release_object( mailslot );
  398. return NULL;
  399. }
  400. static void mail_writer_dump( struct object *obj, int verbose )
  401. {
  402. fprintf( stderr, "Mailslot writer\n" );
  403. }
  404. static void mail_writer_destroy( struct object *obj)
  405. {
  406. struct mail_writer *writer = (struct mail_writer *) obj;
  407. if (writer->fd) release_object( writer->fd );
  408. list_remove( &writer->entry );
  409. release_object( writer->mailslot );
  410. }
  411. static enum server_fd_type mail_writer_get_fd_type( struct fd *fd )
  412. {
  413. return FD_TYPE_MAILSLOT;
  414. }
  415. static struct fd *mail_writer_get_fd( struct object *obj )
  416. {
  417. struct mail_writer *writer = (struct mail_writer *) obj;
  418. return (struct fd *)grab_object( writer->fd );
  419. }
  420. static unsigned int mail_writer_map_access( struct object *obj, unsigned int access )
  421. {
  422. /* mailslot writers can only get write access */
  423. if (access & GENERIC_WRITE) access |= FILE_GENERIC_WRITE;
  424. if (access & GENERIC_ALL) access |= FILE_GENERIC_WRITE;
  425. return access & ~(GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE | GENERIC_ALL);
  426. }
  427. static struct mailslot *get_mailslot_obj( struct process *process, obj_handle_t handle,
  428. unsigned int access )
  429. {
  430. return (struct mailslot *)get_handle_obj( process, handle, access, &mailslot_ops );
  431. }
  432. /* create a mailslot */
  433. DECL_HANDLER(create_mailslot)
  434. {
  435. struct mailslot *mailslot;
  436. struct unicode_str name;
  437. struct object *root;
  438. const struct security_descriptor *sd;
  439. const struct object_attributes *objattr = get_req_object_attributes( &sd, &name, &root );
  440. if (!objattr) return;
  441. if (!name.len) /* mailslots need a root directory even without a name */
  442. {
  443. if (!objattr->rootdir)
  444. {
  445. set_error( STATUS_OBJECT_PATH_SYNTAX_BAD );
  446. return;
  447. }
  448. if (!(root = get_directory_obj( current->process, objattr->rootdir ))) return;
  449. }
  450. if ((mailslot = create_mailslot( root, &name, objattr->attributes, req->max_msgsize,
  451. req->read_timeout, sd )))
  452. {
  453. reply->handle = alloc_handle( current->process, mailslot, req->access, objattr->attributes );
  454. release_object( mailslot );
  455. }
  456. if (root) release_object( root );
  457. }
  458. /* set mailslot information */
  459. DECL_HANDLER(set_mailslot_info)
  460. {
  461. struct mailslot *mailslot = get_mailslot_obj( current->process, req->handle, 0 );
  462. if (mailslot)
  463. {
  464. if (req->flags & MAILSLOT_SET_READ_TIMEOUT)
  465. mailslot->read_timeout = req->read_timeout;
  466. reply->max_msgsize = mailslot->max_msgsize;
  467. reply->read_timeout = mailslot->read_timeout;
  468. release_object( mailslot );
  469. }
  470. }