Extended __wine_enter_vm86 to handle pending interrupts.
[wine/multimedia.git] / server / queue.c
blob7e94cde5cb7ae617e299c9b89312b5e9c5c87718
1 /*
2 * Server-side message queues
4 * Copyright (C) 2000 Alexandre Julliard
5 */
7 #include <assert.h>
8 #include <stdio.h>
9 #include <stdlib.h>
11 #include "winbase.h"
12 #include "wingdi.h"
13 #include "winuser.h"
15 #include "handle.h"
16 #include "thread.h"
17 #include "process.h"
18 #include "request.h"
20 struct message_result
22 struct message_result *send_next; /* next in sender list */
23 struct message_result *recv_next; /* next in receiver list */
24 struct msg_queue *sender; /* sender queue */
25 struct msg_queue *receiver; /* receiver queue */
26 int replied; /* has it been replied to? */
27 unsigned int result; /* reply result */
28 unsigned int error; /* error code to pass back to sender */
31 struct message
33 struct message *next; /* next message in list */
34 struct message *prev; /* prev message in list */
35 int type; /* message type (FIXME) */
36 handle_t win; /* window handle */
37 unsigned int msg; /* message code */
38 unsigned int wparam; /* parameters */
39 unsigned int lparam; /* parameters */
40 unsigned short x; /* x position */
41 unsigned short y; /* y position */
42 unsigned int time; /* message time */
43 unsigned int info; /* extra info */
44 struct message_result *result; /* result in sender queue */
47 struct message_list
49 struct message *first; /* head of list */
50 struct message *last; /* tail of list */
53 struct timer
55 struct timer *next; /* next timer in list */
56 struct timer *prev; /* prev timer in list */
57 struct timeval when; /* next expiration */
58 unsigned int rate; /* timer rate in ms */
59 handle_t win; /* window handle */
60 unsigned int msg; /* message to post */
61 unsigned int id; /* timer id */
62 unsigned int lparam; /* lparam for message */
65 struct msg_queue
67 struct object obj; /* object header */
68 unsigned int wake_bits; /* wakeup bits */
69 unsigned int wake_mask; /* wakeup mask */
70 unsigned int changed_bits; /* changed wakeup bits */
71 unsigned int changed_mask; /* changed wakeup mask */
72 int paint_count; /* pending paint messages count */
73 struct message_list msg_list[NB_MSG_KINDS]; /* lists of messages */
74 struct message_result *send_result; /* stack of sent messages waiting for result */
75 struct message_result *recv_result; /* stack of received messages waiting for result */
76 struct timer *first_timer; /* head of timer list */
77 struct timer *last_timer; /* tail of timer list */
78 struct timer *next_timer; /* next timer to expire */
79 struct timeout_user *timeout; /* timeout for next timer to expire */
82 static void msg_queue_dump( struct object *obj, int verbose );
83 static int msg_queue_add_queue( struct object *obj, struct wait_queue_entry *entry );
84 static void msg_queue_remove_queue( struct object *obj, struct wait_queue_entry *entry );
85 static int msg_queue_signaled( struct object *obj, struct thread *thread );
86 static int msg_queue_satisfied( struct object *obj, struct thread *thread );
87 static void msg_queue_destroy( struct object *obj );
88 static void timer_callback( void *private );
90 static const struct object_ops msg_queue_ops =
92 sizeof(struct msg_queue), /* size */
93 msg_queue_dump, /* dump */
94 msg_queue_add_queue, /* add_queue */
95 msg_queue_remove_queue, /* remove_queue */
96 msg_queue_signaled, /* signaled */
97 msg_queue_satisfied, /* satisfied */
98 NULL, /* get_poll_events */
99 NULL, /* poll_event */
100 no_get_fd, /* get_fd */
101 no_flush, /* flush */
102 no_get_file_info, /* get_file_info */
103 msg_queue_destroy /* destroy */
107 static struct msg_queue *create_msg_queue( struct thread *thread )
109 struct msg_queue *queue;
110 int i;
112 if ((queue = alloc_object( &msg_queue_ops, -1 )))
114 queue->wake_bits = 0;
115 queue->wake_mask = 0;
116 queue->changed_bits = 0;
117 queue->changed_mask = 0;
118 queue->paint_count = 0;
119 queue->send_result = NULL;
120 queue->recv_result = NULL;
121 queue->first_timer = NULL;
122 queue->last_timer = NULL;
123 queue->next_timer = NULL;
124 queue->timeout = NULL;
125 for (i = 0; i < NB_MSG_KINDS; i++)
126 queue->msg_list[i].first = queue->msg_list[i].last = NULL;
128 thread->queue = queue;
129 if (!thread->process->queue)
130 thread->process->queue = (struct msg_queue *)grab_object( queue );
132 return queue;
135 /* check the queue status */
136 inline static int is_signaled( struct msg_queue *queue )
138 return ((queue->wake_bits & queue->wake_mask) || (queue->changed_bits & queue->changed_mask));
141 /* set/clear some queue bits */
142 inline static void change_queue_bits( struct msg_queue *queue, unsigned int set, unsigned int clear )
144 queue->wake_bits = (queue->wake_bits | set) & ~clear;
145 queue->changed_bits = (queue->changed_bits | set) & ~clear;
146 if (is_signaled( queue )) wake_up( &queue->obj, 0 );
149 /* get the QS_* bit corresponding to a given hardware message */
150 inline static int get_hardware_msg_bit( struct message *msg )
152 if (msg->msg == WM_MOUSEMOVE || msg->msg == WM_NCMOUSEMOVE) return QS_MOUSEMOVE;
153 if (msg->msg >= WM_KEYFIRST && msg->msg <= WM_KEYLAST) return QS_KEY;
154 return QS_MOUSEBUTTON;
157 /* get the current thread queue, creating it if needed */
158 inline struct msg_queue *get_current_queue(void)
160 struct msg_queue *queue = current->queue;
161 if (!queue) queue = create_msg_queue( current );
162 return queue;
165 /* append a message to the end of a list */
166 inline static void append_message( struct message_list *list, struct message *msg )
168 msg->next = NULL;
169 if ((msg->prev = list->last)) msg->prev->next = msg;
170 else list->first = msg;
171 list->last = msg;
174 /* unlink a message from a list it */
175 inline static void unlink_message( struct message_list *list, struct message *msg )
177 if (msg->next) msg->next->prev = msg->prev;
178 else list->last = msg->prev;
179 if (msg->prev) msg->prev->next = msg->next;
180 else list->first = msg->next;
183 /* free a message when deleting a queue or window */
184 static void free_message( struct message *msg )
186 struct message_result *result = msg->result;
187 if (result)
189 if (result->sender)
191 result->result = 0;
192 result->error = STATUS_ACCESS_DENIED; /* FIXME */
193 result->replied = 1;
194 result->receiver = NULL;
195 /* wake sender queue if waiting on this result */
196 if (result->sender->send_result == result)
197 change_queue_bits( result->sender, QS_SMRESULT, 0 );
199 else free( result );
201 free( msg );
204 /* remove (and free) a message from a message list */
205 static void remove_queue_message( struct msg_queue *queue, struct message *msg,
206 enum message_kind kind )
208 int clr_bit;
209 struct message *other;
211 unlink_message( &queue->msg_list[kind], msg );
212 switch(kind)
214 case SEND_MESSAGE:
215 if (!queue->msg_list[kind].first) change_queue_bits( queue, 0, QS_SENDMESSAGE );
216 break;
217 case POST_MESSAGE:
218 if (!queue->msg_list[kind].first) change_queue_bits( queue, 0, QS_POSTMESSAGE );
219 break;
220 case COOKED_HW_MESSAGE:
221 case RAW_HW_MESSAGE:
222 clr_bit = get_hardware_msg_bit( msg );
223 for (other = queue->msg_list[kind].first; other; other = other->next)
224 if (get_hardware_msg_bit( other ) == clr_bit) break;
225 if (!other) change_queue_bits( queue, 0, clr_bit );
226 break;
228 free_message( msg );
231 /* send a message from the sender queue to the receiver queue */
232 static int send_message( struct msg_queue *send_queue, struct msg_queue *recv_queue,
233 struct message *msg )
235 struct message_result *result = mem_alloc( sizeof(*result) );
236 if (!result) return 0;
238 /* put the result on the sender result stack */
239 result->sender = send_queue;
240 result->receiver = recv_queue;
241 result->replied = 0;
242 result->send_next = send_queue->send_result;
243 send_queue->send_result = result;
245 /* and put the message on the receiver queue */
246 msg->result = result;
247 append_message( &recv_queue->msg_list[SEND_MESSAGE], msg );
248 change_queue_bits( recv_queue, QS_SENDMESSAGE, 0 );
249 return 1;
252 /* receive a message, removing it from the sent queue */
253 static void receive_message( struct msg_queue *queue, struct message *msg )
255 struct message_result *result = msg->result;
257 unlink_message( &queue->msg_list[SEND_MESSAGE], msg );
258 /* put the result on the receiver result stack */
259 result->recv_next = queue->recv_result;
260 queue->recv_result = result;
261 free( msg );
262 if (!queue->msg_list[SEND_MESSAGE].first) change_queue_bits( queue, 0, QS_SENDMESSAGE );
265 /* set the result of the current received message */
266 static void reply_message( struct msg_queue *queue, unsigned int result,
267 unsigned int error, int remove )
269 struct message_result *res = queue->recv_result;
271 if (remove)
273 queue->recv_result = res->recv_next;
274 res->receiver = NULL;
275 if (!res->sender) /* no one waiting for it */
277 free( res );
278 return;
281 if (!res->replied)
283 res->result = result;
284 res->error = error;
285 res->replied = 1;
286 /* wake sender queue if waiting on this result */
287 if (res->sender && res->sender->send_result == res)
288 change_queue_bits( res->sender, QS_SMRESULT, 0 );
292 /* retrieve the reply of the current message being sent */
293 static unsigned int get_message_reply( struct msg_queue *queue, int cancel )
295 struct message_result *res = queue->send_result;
296 unsigned int ret = 0;
298 set_error( STATUS_PENDING );
300 if (res && (res->replied || cancel))
302 if (res->replied)
304 ret = res->result;
305 set_error( res->error );
307 queue->send_result = res->send_next;
308 res->sender = NULL;
309 if (!res->receiver) free( res );
310 if (!queue->send_result || !queue->send_result->replied)
311 change_queue_bits( queue, 0, QS_SMRESULT );
313 return ret;
316 /* empty a message list and free all the messages */
317 static void empty_msg_list( struct message_list *list )
319 struct message *msg = list->first;
320 while (msg)
322 struct message *next = msg->next;
323 free_message( msg );
324 msg = next;
328 /* cleanup all pending results when deleting a queue */
329 static void cleanup_results( struct msg_queue *queue )
331 struct message_result *result, *next;
333 result = queue->send_result;
334 while (result)
336 next = result->send_next;
337 result->sender = NULL;
338 if (!result->receiver) free( result );
339 result = next;
342 while (queue->recv_result) reply_message( queue, 0, STATUS_ACCESS_DENIED /*FIXME*/, 1 );
345 static int msg_queue_add_queue( struct object *obj, struct wait_queue_entry *entry )
347 struct msg_queue *queue = (struct msg_queue *)obj;
348 struct process *process = entry->thread->process;
350 /* a thread can only wait on its own queue */
351 if (entry->thread->queue != queue)
353 set_error( STATUS_ACCESS_DENIED );
354 return 0;
356 /* if waiting on the main process queue, set the idle event */
357 if (process->queue == queue)
359 if (process->idle_event) set_event( process->idle_event );
361 add_queue( obj, entry );
362 return 1;
365 static void msg_queue_remove_queue(struct object *obj, struct wait_queue_entry *entry )
367 struct msg_queue *queue = (struct msg_queue *)obj;
368 struct process *process = entry->thread->process;
370 remove_queue( obj, entry );
372 assert( entry->thread->queue == queue );
374 /* if waiting on the main process queue, reset the idle event */
375 if (process->queue == queue)
377 if (process->idle_event) reset_event( process->idle_event );
381 static void msg_queue_dump( struct object *obj, int verbose )
383 struct msg_queue *queue = (struct msg_queue *)obj;
384 fprintf( stderr, "Msg queue bits=%x mask=%x\n",
385 queue->wake_bits, queue->wake_mask );
388 static int msg_queue_signaled( struct object *obj, struct thread *thread )
390 struct msg_queue *queue = (struct msg_queue *)obj;
391 return is_signaled( queue );
394 static int msg_queue_satisfied( struct object *obj, struct thread *thread )
396 struct msg_queue *queue = (struct msg_queue *)obj;
397 queue->wake_mask = 0;
398 queue->changed_mask = 0;
399 return 0; /* Not abandoned */
402 static void msg_queue_destroy( struct object *obj )
404 struct msg_queue *queue = (struct msg_queue *)obj;
405 struct timer *timer = queue->first_timer;
406 int i;
408 cleanup_results( queue );
409 for (i = 0; i < NB_MSG_KINDS; i++) empty_msg_list( &queue->msg_list[i] );
411 while (timer)
413 struct timer *next = timer->next;
414 free( timer );
415 timer = next;
417 if (queue->timeout) remove_timeout_user( queue->timeout );
420 /* set the next timer to expire */
421 static void set_next_timer( struct msg_queue *queue, struct timer *timer )
423 if (queue->timeout)
425 remove_timeout_user( queue->timeout );
426 queue->timeout = NULL;
428 if ((queue->next_timer = timer))
429 queue->timeout = add_timeout_user( &timer->when, timer_callback, queue );
431 /* set/clear QS_TIMER bit */
432 if (queue->next_timer == queue->first_timer)
433 change_queue_bits( queue, 0, QS_TIMER );
434 else
435 change_queue_bits( queue, QS_TIMER, 0 );
438 /* callback for the next timer expiration */
439 static void timer_callback( void *private )
441 struct msg_queue *queue = private;
443 queue->timeout = NULL;
444 /* move on to the next timer */
445 set_next_timer( queue, queue->next_timer->next );
448 /* link a timer at its rightful place in the queue list */
449 static void link_timer( struct msg_queue *queue, struct timer *timer )
451 struct timer *pos = queue->next_timer;
453 while (pos && time_before( &pos->when, &timer->when )) pos = pos->next;
455 if (pos) /* insert before pos */
457 if ((timer->prev = pos->prev)) timer->prev->next = timer;
458 else queue->first_timer = timer;
459 timer->next = pos;
460 pos->prev = timer;
462 else /* insert at end */
464 timer->next = NULL;
465 timer->prev = queue->last_timer;
466 if (queue->last_timer) queue->last_timer->next = timer;
467 else queue->first_timer = timer;
468 queue->last_timer = timer;
470 /* check if we replaced the next timer */
471 if (pos == queue->next_timer) set_next_timer( queue, timer );
474 /* remove a timer from the queue timer list */
475 static void unlink_timer( struct msg_queue *queue, struct timer *timer )
477 if (timer->next) timer->next->prev = timer->prev;
478 else queue->last_timer = timer->prev;
479 if (timer->prev) timer->prev->next = timer->next;
480 else queue->first_timer = timer->next;
481 /* check if we removed the next timer */
482 if (queue->next_timer == timer) set_next_timer( queue, timer->next );
483 else if (queue->next_timer == queue->first_timer) change_queue_bits( queue, 0, QS_TIMER );
486 /* restart an expired timer */
487 static void restart_timer( struct msg_queue *queue, struct timer *timer )
489 struct timeval now;
490 unlink_timer( queue, timer );
491 gettimeofday( &now, 0 );
492 while (!time_before( &now, &timer->when )) add_timeout( &timer->when, timer->rate );
493 link_timer( queue, timer );
496 /* find an expired timer matching the filtering parameters */
497 static struct timer *find_expired_timer( struct msg_queue *queue, handle_t win,
498 unsigned int get_first, unsigned int get_last,
499 int remove )
501 struct timer *timer;
502 for (timer = queue->first_timer; (timer && timer != queue->next_timer); timer = timer->next)
504 if (win && timer->win != win) continue;
505 if (timer->msg >= get_first && timer->msg <= get_last)
507 if (remove) restart_timer( queue, timer );
508 return timer;
511 return NULL;
514 /* kill a timer */
515 static int kill_timer( struct msg_queue *queue, handle_t win, unsigned int msg, unsigned int id )
517 struct timer *timer;
519 for (timer = queue->first_timer; timer; timer = timer->next)
521 if (timer->win != win || timer->msg != msg || timer->id != id) continue;
522 unlink_timer( queue, timer );
523 free( timer );
524 return 1;
526 return 0;
529 /* add a timer */
530 static struct timer *set_timer( struct msg_queue *queue, unsigned int rate )
532 struct timer *timer = mem_alloc( sizeof(*timer) );
533 if (timer)
535 timer->rate = rate;
536 gettimeofday( &timer->when, 0 );
537 add_timeout( &timer->when, rate );
538 link_timer( queue, timer );
540 return timer;
543 /* remove all messages and timers belonging to a certain window */
544 static void cleanup_window( struct msg_queue *queue, handle_t win )
546 struct timer *timer;
547 struct message *msg;
548 int i;
550 /* remove timers */
551 timer = queue->first_timer;
552 while (timer)
554 struct timer *next = timer->next;
555 if (timer->win == win)
557 unlink_timer( queue, timer );
558 free( timer );
560 timer = next;
563 /* remove messages */
564 for (i = 0; i < NB_MSG_KINDS; i++)
566 msg = queue->msg_list[i].first;
567 while (msg)
569 struct message *next = msg->next;
570 if (msg->win == win) remove_queue_message( queue, msg, i );
571 msg = next;
576 /* get the message queue of the current thread */
577 DECL_HANDLER(get_msg_queue)
579 struct msg_queue *queue = get_current_queue();
581 req->handle = 0;
582 if (queue) req->handle = alloc_handle( current->process, queue, SYNCHRONIZE, 0 );
586 /* increment the message queue paint count */
587 DECL_HANDLER(inc_queue_paint_count)
589 struct msg_queue *queue;
590 struct thread *thread = get_thread_from_id( req->id );
592 if (!thread) return;
594 if ((queue = thread->queue))
596 if ((queue->paint_count += req->incr) < 0) queue->paint_count = 0;
598 if (queue->paint_count)
599 change_queue_bits( queue, QS_PAINT, 0 );
600 else
601 change_queue_bits( queue, 0, QS_PAINT );
603 else set_error( STATUS_INVALID_PARAMETER );
605 release_object( thread );
610 /* set the current message queue wakeup mask */
611 DECL_HANDLER(set_queue_mask)
613 struct msg_queue *queue = get_current_queue();
615 if (queue)
617 queue->wake_mask = req->wake_mask;
618 queue->changed_mask = req->changed_mask;
619 req->wake_bits = queue->wake_bits;
620 req->changed_bits = queue->changed_bits;
621 if (is_signaled( queue ))
623 /* if skip wait is set, do what would have been done in the subsequent wait */
624 if (req->skip_wait) msg_queue_satisfied( &queue->obj, current );
625 else wake_up( &queue->obj, 0 );
631 /* get the current message queue status */
632 DECL_HANDLER(get_queue_status)
634 struct msg_queue *queue = current->queue;
635 if (queue)
637 req->wake_bits = queue->wake_bits;
638 req->changed_bits = queue->changed_bits;
639 if (req->clear) queue->changed_bits = 0;
641 else req->wake_bits = req->changed_bits = 0;
645 /* send a message to a thread queue */
646 DECL_HANDLER(send_message)
648 struct message *msg;
649 struct msg_queue *send_queue = get_current_queue();
650 struct msg_queue *recv_queue;
651 struct thread *thread = get_thread_from_id( req->id );
653 if (!thread) return;
655 if (!(recv_queue = thread->queue))
657 set_error( STATUS_INVALID_PARAMETER );
658 release_object( thread );
659 return;
662 if ((msg = mem_alloc( sizeof(*msg) )))
664 msg->type = req->type;
665 msg->win = req->win;
666 msg->msg = req->msg;
667 msg->wparam = req->wparam;
668 msg->lparam = req->lparam;
669 msg->x = req->x;
670 msg->y = req->y;
671 msg->time = req->time;
672 msg->info = req->info;
673 msg->result = NULL;
674 switch(req->kind)
676 case SEND_MESSAGE:
677 send_message( send_queue, recv_queue, msg );
678 break;
679 case POST_MESSAGE:
680 append_message( &recv_queue->msg_list[POST_MESSAGE], msg );
681 change_queue_bits( recv_queue, QS_POSTMESSAGE, 0 );
682 break;
683 case COOKED_HW_MESSAGE:
684 case RAW_HW_MESSAGE:
685 append_message( &recv_queue->msg_list[req->kind], msg );
686 change_queue_bits( recv_queue, get_hardware_msg_bit(msg), 0 );
687 break;
688 default:
689 free( msg );
690 set_error( STATUS_INVALID_PARAMETER );
691 break;
694 release_object( thread );
697 /* store a message contents into the request buffer; helper for get_message */
698 inline static void put_req_message( struct get_message_request *req, const struct message *msg )
700 req->type = msg->type;
701 req->win = msg->win;
702 req->msg = msg->msg;
703 req->wparam = msg->wparam;
704 req->lparam = msg->lparam;
705 req->x = msg->x;
706 req->y = msg->y;
707 req->time = msg->time;
708 req->info = msg->info;
711 inline static struct message *find_matching_message( const struct message_list *list, handle_t win,
712 unsigned int first, unsigned int last )
714 struct message *msg;
716 for (msg = list->first; msg; msg = msg->next)
718 /* check against the filters */
719 if (win && msg->win && msg->win != win) continue;
720 if (msg->msg < first) continue;
721 if (msg->msg > last) continue;
722 break; /* found one */
724 return msg;
728 /* get a message from the current queue */
729 DECL_HANDLER(get_message)
731 struct timer *timer;
732 struct message *msg;
733 struct msg_queue *queue = get_current_queue();
735 if (!queue) return;
737 /* first check for sent messages */
738 if ((msg = queue->msg_list[SEND_MESSAGE].first))
740 req->kind = SEND_MESSAGE;
741 put_req_message( req, msg );
742 receive_message( queue, msg );
743 return;
745 if (req->flags & GET_MSG_SENT_ONLY) goto done; /* nothing else to check */
747 /* then check for posted messages */
748 if ((msg = find_matching_message( &queue->msg_list[POST_MESSAGE], req->get_win,
749 req->get_first, req->get_last )))
751 req->kind = POST_MESSAGE;
752 put_req_message( req, msg );
753 if (req->flags & GET_MSG_REMOVE) remove_queue_message( queue, msg, POST_MESSAGE );
754 return;
757 /* then check for cooked hardware messages */
758 if ((msg = find_matching_message( &queue->msg_list[COOKED_HW_MESSAGE], req->get_win,
759 req->get_first, req->get_last )))
761 req->kind = COOKED_HW_MESSAGE;
762 put_req_message( req, msg );
763 if (req->flags & GET_MSG_REMOVE) remove_queue_message( queue, msg, COOKED_HW_MESSAGE );
764 return;
767 /* then check for any raw hardware message */
768 if ((msg = queue->msg_list[RAW_HW_MESSAGE].first))
770 req->kind = RAW_HW_MESSAGE;
771 put_req_message( req, msg );
772 /* raw messages always get removed */
773 remove_queue_message( queue, msg, RAW_HW_MESSAGE );
774 return;
777 /* now check for WM_PAINT */
778 if ((queue->wake_bits & QS_PAINT) &&
779 (WM_PAINT >= req->get_first) && (WM_PAINT <= req->get_last))
781 req->kind = POST_MESSAGE;
782 req->type = 0;
783 req->win = 0;
784 req->msg = WM_PAINT;
785 req->wparam = 0;
786 req->lparam = 0;
787 req->x = 0;
788 req->y = 0;
789 req->time = 0;
790 req->info = 0;
791 return;
794 /* now check for timer */
795 if ((timer = find_expired_timer( queue, req->get_win, req->get_first,
796 req->get_last, (req->flags & GET_MSG_REMOVE) )))
798 req->kind = POST_MESSAGE;
799 req->type = 0;
800 req->win = timer->win;
801 req->msg = timer->msg;
802 req->wparam = timer->id;
803 req->lparam = timer->lparam;
804 req->x = 0;
805 req->y = 0;
806 req->time = 0;
807 req->info = 0;
808 return;
811 done:
812 set_error( STATUS_PENDING ); /* FIXME */
816 /* reply to a sent message */
817 DECL_HANDLER(reply_message)
819 if (current->queue && current->queue->recv_result)
820 reply_message( current->queue, req->result, 0, req->remove );
821 else
822 set_error( STATUS_ACCESS_DENIED );
826 /* retrieve the reply for the last message sent */
827 DECL_HANDLER(get_message_reply)
829 if (current->queue) req->result = get_message_reply( current->queue, req->cancel );
830 else set_error( STATUS_ACCESS_DENIED );
834 /* check if we are processing a sent message */
835 DECL_HANDLER(in_send_message)
837 int flags = 0;
839 if (current->queue)
841 struct message_result *result = current->queue->recv_result;
842 if (result)
844 flags |= ISMEX_SEND; /* FIXME */
845 if (result->replied || !result->sender) flags |= ISMEX_REPLIED;
848 req->flags = flags;
852 /* cleanup a queue when a window is deleted */
853 DECL_HANDLER(cleanup_window_queue)
855 if (current->queue) cleanup_window( current->queue, req->win );
859 /* set a window timer */
860 DECL_HANDLER(set_win_timer)
862 struct timer *timer;
863 struct msg_queue *queue = get_current_queue();
865 if (!queue) return;
867 /* remove it if it existed already */
868 if (req->win) kill_timer( queue, req->win, req->msg, req->id );
870 if ((timer = set_timer( queue, req->rate )))
872 timer->win = req->win;
873 timer->msg = req->msg;
874 timer->id = req->id;
875 timer->lparam = req->lparam;
879 /* kill a window timer */
880 DECL_HANDLER(kill_win_timer)
882 struct msg_queue *queue = current->queue;
884 if (!queue || !kill_timer( queue, req->win, req->msg, req->id ))
885 set_error( STATUS_INVALID_PARAMETER );