mailslot.c 20 KB

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