Fixed test so 0xffffffff is properly recognized.
[wine] / server / queue.c
1 /*
2  * Server-side message queues
3  *
4  * Copyright (C) 2000 Alexandre Julliard
5  */
6
7 #include <assert.h>
8 #include <stdio.h>
9 #include <stdlib.h>
10
11 #include "winbase.h"
12 #include "wingdi.h"
13 #include "winuser.h"
14
15 #include "handle.h"
16 #include "thread.h"
17 #include "process.h"
18 #include "request.h"
19
20 struct message_result
21 {
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 */
29 };
30
31 struct message
32 {
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 */
45 };
46
47 struct message_list
48 {
49     struct message *first;     /* head of list */
50     struct message *last;      /* tail of list */
51 };
52
53 struct timer
54 {
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 */
63 };
64
65 struct msg_queue
66 {
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 */
80 };
81
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 );
89
90 static const struct object_ops msg_queue_ops =
91 {
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 */
104 };
105
106
107 static struct msg_queue *create_msg_queue( struct thread *thread )
108 {
109     struct msg_queue *queue;
110     int i;
111
112     if ((queue = alloc_object( &msg_queue_ops, -1 )))
113     {
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;
127
128         thread->queue = queue;
129         if (!thread->process->queue)
130             thread->process->queue = (struct msg_queue *)grab_object( queue );
131     }
132     return queue;
133 }
134
135 /* check the queue status */
136 inline static int is_signaled( struct msg_queue *queue )
137 {
138     return ((queue->wake_bits & queue->wake_mask) || (queue->changed_bits & queue->changed_mask));
139 }
140
141 /* set/clear some queue bits */
142 inline static void change_queue_bits( struct msg_queue *queue, unsigned int set, unsigned int clear )
143 {
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 );
147 }
148
149 /* get the QS_* bit corresponding to a given hardware message */
150 inline static int get_hardware_msg_bit( struct message *msg )
151 {
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;
155 }
156
157 /* get the current thread queue, creating it if needed */
158 inline struct msg_queue *get_current_queue(void)
159 {
160     struct msg_queue *queue = current->queue;
161     if (!queue) queue = create_msg_queue( current );
162     return queue;
163 }
164
165 /* append a message to the end of a list */
166 inline static void append_message( struct message_list *list, struct message *msg )
167 {
168     msg->next = NULL;
169     if ((msg->prev = list->last)) msg->prev->next = msg;
170     else list->first = msg;
171     list->last = msg;
172 }
173
174 /* unlink a message from a list it */
175 inline static void unlink_message( struct message_list *list, struct message *msg )
176 {
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;
181 }
182
183 /* free a message when deleting a queue or window */
184 static void free_message( struct message *msg )
185 {
186     struct message_result *result = msg->result;
187     if (result)
188     {
189         if (result->sender)
190         {
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 );
198         }
199         else free( result );
200     }
201     free( msg );
202 }
203
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 )
207 {
208     int clr_bit;
209     struct message *other;
210
211     unlink_message( &queue->msg_list[kind], msg );
212     switch(kind)
213     {
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;
227     }
228     free_message( msg );
229 }
230
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 )
234 {
235     struct message_result *result = mem_alloc( sizeof(*result) );
236     if (!result) return 0;
237
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;
244
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;
250 }
251
252 /* receive a message, removing it from the sent queue */
253 static void receive_message( struct msg_queue *queue, struct message *msg )
254 {
255     struct message_result *result = msg->result;
256
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 );
263 }
264
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 )
268 {
269     struct message_result *res = queue->recv_result;
270
271     if (remove)
272     {
273         queue->recv_result = res->recv_next;
274         res->receiver = NULL;
275         if (!res->sender)  /* no one waiting for it */
276         {
277             free( res );
278             return;
279         }
280     }
281     if (!res->replied)
282     {
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 );
289     }
290 }
291
292 /* retrieve the reply of the current message being sent */
293 static unsigned int get_message_reply( struct msg_queue *queue, int cancel )
294 {
295     struct message_result *res = queue->send_result;
296     unsigned int ret = 0;
297
298     set_error( STATUS_PENDING );
299
300     if (res && (res->replied || cancel))
301     {
302         if (res->replied)
303         {
304             ret = res->result;
305             set_error( res->error );
306         }
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 );
312     }
313     return ret;
314 }
315
316 /* empty a message list and free all the messages */
317 static void empty_msg_list( struct message_list *list )
318 {
319     struct message *msg = list->first;
320     while (msg)
321     {
322         struct message *next = msg->next;
323         free_message( msg );
324         msg = next;
325     }
326 }
327
328 /* cleanup all pending results when deleting a queue */
329 static void cleanup_results( struct msg_queue *queue )
330 {
331     struct message_result *result, *next;
332
333     result = queue->send_result;
334     while (result)
335     {
336         next = result->send_next;
337         result->sender = NULL;
338         if (!result->receiver) free( result );
339         result = next;
340     }
341
342     while (queue->recv_result) reply_message( queue, 0, STATUS_ACCESS_DENIED /*FIXME*/, 1 );
343 }
344
345 static int msg_queue_add_queue( struct object *obj, struct wait_queue_entry *entry )
346 {
347     struct msg_queue *queue = (struct msg_queue *)obj;
348     struct process *process = entry->thread->process;
349
350     /* a thread can only wait on its own queue */
351     if (entry->thread->queue != queue)
352     {
353         set_error( STATUS_ACCESS_DENIED );
354         return 0;
355     }
356     /* if waiting on the main process queue, set the idle event */
357     if (process->queue == queue)
358     {
359         if (process->idle_event) set_event( process->idle_event );
360     }
361     add_queue( obj, entry );
362     return 1;
363 }
364
365 static void msg_queue_remove_queue(struct object *obj, struct wait_queue_entry *entry )
366 {
367     struct msg_queue *queue = (struct msg_queue *)obj;
368     struct process *process = entry->thread->process;
369
370     remove_queue( obj, entry );
371
372     assert( entry->thread->queue == queue );
373
374     /* if waiting on the main process queue, reset the idle event */
375     if (process->queue == queue)
376     {
377         if (process->idle_event) reset_event( process->idle_event );
378     }
379 }
380
381 static void msg_queue_dump( struct object *obj, int verbose )
382 {
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 );
386 }
387
388 static int msg_queue_signaled( struct object *obj, struct thread *thread )
389 {
390     struct msg_queue *queue = (struct msg_queue *)obj;
391     return is_signaled( queue );
392 }
393
394 static int msg_queue_satisfied( struct object *obj, struct thread *thread )
395 {
396     struct msg_queue *queue = (struct msg_queue *)obj;
397     queue->wake_mask = 0;
398     queue->changed_mask = 0;
399     return 0;  /* Not abandoned */
400 }
401
402 static void msg_queue_destroy( struct object *obj )
403 {
404     struct msg_queue *queue = (struct msg_queue *)obj;
405     struct timer *timer = queue->first_timer;
406     int i;
407
408     cleanup_results( queue );
409     for (i = 0; i < NB_MSG_KINDS; i++) empty_msg_list( &queue->msg_list[i] );
410
411     while (timer)
412     {
413         struct timer *next = timer->next;
414         free( timer );
415         timer = next;
416     }
417     if (queue->timeout) remove_timeout_user( queue->timeout );
418 }
419
420 /* set the next timer to expire */
421 static void set_next_timer( struct msg_queue *queue, struct timer *timer )
422 {
423     if (queue->timeout)
424     {
425         remove_timeout_user( queue->timeout );
426         queue->timeout = NULL;
427     }
428     if ((queue->next_timer = timer))
429         queue->timeout = add_timeout_user( &timer->when, timer_callback, queue );
430
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 );
436 }
437
438 /* callback for the next timer expiration */
439 static void timer_callback( void *private )
440 {
441     struct msg_queue *queue = private;
442
443     queue->timeout = NULL;
444     /* move on to the next timer */
445     set_next_timer( queue, queue->next_timer->next );
446 }
447
448 /* link a timer at its rightful place in the queue list */
449 static void link_timer( struct msg_queue *queue, struct timer *timer )
450 {
451     struct timer *pos = queue->next_timer;
452
453     while (pos && time_before( &pos->when, &timer->when )) pos = pos->next;
454
455     if (pos) /* insert before pos */
456     {
457         if ((timer->prev = pos->prev)) timer->prev->next = timer;
458         else queue->first_timer = timer;
459         timer->next = pos;
460         pos->prev = timer;
461     }
462     else  /* insert at end */
463     {
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;
469     }
470     /* check if we replaced the next timer */
471     if (pos == queue->next_timer) set_next_timer( queue, timer );
472 }
473
474 /* remove a timer from the queue timer list */
475 static void unlink_timer( struct msg_queue *queue, struct timer *timer )
476 {
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 );
484 }
485
486 /* restart an expired timer */
487 static void restart_timer( struct msg_queue *queue, struct timer *timer )
488 {
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 );
494 }
495
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 )
500 {
501     struct timer *timer;
502     for (timer = queue->first_timer; (timer && timer != queue->next_timer); timer = timer->next)
503     {
504         if (win && timer->win != win) continue;
505         if (timer->msg >= get_first && timer->msg <= get_last)
506         {
507             if (remove) restart_timer( queue, timer );
508             return timer;
509         }
510     }
511     return NULL;
512 }
513
514 /* kill a timer */
515 static int kill_timer( struct msg_queue *queue, handle_t win, unsigned int msg, unsigned int id )
516 {
517     struct timer *timer;
518
519     for (timer = queue->first_timer; timer; timer = timer->next)
520     {
521         if (timer->win != win || timer->msg != msg || timer->id != id) continue;
522         unlink_timer( queue, timer );
523         free( timer );
524         return 1;
525     }
526     return 0;
527 }
528
529 /* add a timer */
530 static struct timer *set_timer( struct msg_queue *queue, unsigned int rate )
531 {
532     struct timer *timer = mem_alloc( sizeof(*timer) );
533     if (timer)
534     {
535         timer->rate  = rate;
536         gettimeofday( &timer->when, 0 );
537         add_timeout( &timer->when, rate );
538         link_timer( queue, timer );
539     }
540     return timer;
541 }
542
543 /* remove all messages and timers belonging to a certain window */
544 static void cleanup_window( struct msg_queue *queue, handle_t win )
545 {
546     struct timer *timer;
547     struct message *msg;
548     int i;
549
550     /* remove timers */
551     timer = queue->first_timer;
552     while (timer)
553     {
554         struct timer *next = timer->next;
555         if (timer->win == win)
556         {
557             unlink_timer( queue, timer );
558             free( timer );
559         }
560         timer = next;
561     }
562
563     /* remove messages */
564     for (i = 0; i < NB_MSG_KINDS; i++)
565     {
566         msg = queue->msg_list[i].first;
567         while (msg)
568         {
569             struct message *next = msg->next;
570             if (msg->win == win) remove_queue_message( queue, msg, i );
571             msg = next;
572         }
573     }
574 }
575
576 /* get the message queue of the current thread */
577 DECL_HANDLER(get_msg_queue)
578 {
579     struct msg_queue *queue = get_current_queue();
580
581     req->handle = 0;
582     if (queue) req->handle = alloc_handle( current->process, queue, SYNCHRONIZE, 0 );
583 }
584
585
586 /* increment the message queue paint count */
587 DECL_HANDLER(inc_queue_paint_count)
588 {
589     struct msg_queue *queue;
590     struct thread *thread = get_thread_from_id( req->id );
591
592     if (!thread) return;
593
594     if ((queue = thread->queue))
595     {
596         if ((queue->paint_count += req->incr) < 0) queue->paint_count = 0;
597
598         if (queue->paint_count)
599             change_queue_bits( queue, QS_PAINT, 0 );
600         else
601             change_queue_bits( queue, 0, QS_PAINT );
602     }
603     else set_error( STATUS_INVALID_PARAMETER );
604
605     release_object( thread );
606
607 }
608
609
610 /* set the current message queue wakeup mask */
611 DECL_HANDLER(set_queue_mask)
612 {
613     struct msg_queue *queue = get_current_queue();
614
615     if (queue)
616     {
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 ))
622         {
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 );
626         }
627     }
628 }
629
630
631 /* get the current message queue status */
632 DECL_HANDLER(get_queue_status)
633 {
634     struct msg_queue *queue = current->queue;
635     if (queue)
636     {
637         req->wake_bits    = queue->wake_bits;
638         req->changed_bits = queue->changed_bits;
639         if (req->clear) queue->changed_bits = 0;
640     }
641     else req->wake_bits = req->changed_bits = 0;
642 }
643
644
645 /* send a message to a thread queue */
646 DECL_HANDLER(send_message)
647 {
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 );
652
653     if (!thread) return;
654
655     if (!(recv_queue = thread->queue))
656     {
657         set_error( STATUS_INVALID_PARAMETER );
658         release_object( thread );
659         return;
660     }
661
662     if ((msg = mem_alloc( sizeof(*msg) )))
663     {
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)
675         {
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;
692         }
693     }
694     release_object( thread );
695 }
696
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 )
699 {
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;
709 }
710
711 inline static struct message *find_matching_message( const struct message_list *list, handle_t win,
712                                                      unsigned int first, unsigned int last )
713 {
714     struct message *msg;
715
716     for (msg = list->first; msg; msg = msg->next)
717     {
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 */
723     }
724     return msg;
725 }
726
727
728 /* get a message from the current queue */
729 DECL_HANDLER(get_message)
730 {
731     struct timer *timer;
732     struct message *msg;
733     struct msg_queue *queue = get_current_queue();
734
735     if (!queue) return;
736
737     /* first check for sent messages */
738     if ((msg = queue->msg_list[SEND_MESSAGE].first))
739     {
740         req->kind = SEND_MESSAGE;
741         put_req_message( req, msg );
742         receive_message( queue, msg );
743         return;
744     }
745     if (req->flags & GET_MSG_SENT_ONLY) goto done;  /* nothing else to check */
746
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 )))
750     {
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;
755     }
756
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 )))
760     {
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;
765     }
766
767     /* then check for any raw hardware message */
768     if ((msg = queue->msg_list[RAW_HW_MESSAGE].first))
769     {
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;
775     }
776
777     /* now check for WM_PAINT */
778     if ((queue->wake_bits & QS_PAINT) &&
779         (WM_PAINT >= req->get_first) && (WM_PAINT <= req->get_last))
780     {
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;
792     }
793
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) )))
797     {
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;
809     }
810
811  done:
812     set_error( STATUS_PENDING );  /* FIXME */
813 }
814
815
816 /* reply to a sent message */
817 DECL_HANDLER(reply_message)
818 {
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 );
823 }
824
825
826 /* retrieve the reply for the last message sent */
827 DECL_HANDLER(get_message_reply)
828 {
829     if (current->queue) req->result = get_message_reply( current->queue, req->cancel );
830     else set_error( STATUS_ACCESS_DENIED );
831 }
832
833
834 /* check if we are processing a sent message */
835 DECL_HANDLER(in_send_message)
836 {
837     int flags = 0;
838
839     if (current->queue)
840     {
841         struct message_result *result = current->queue->recv_result;
842         if (result)
843         {
844             flags |= ISMEX_SEND;  /* FIXME */
845             if (result->replied || !result->sender) flags |= ISMEX_REPLIED;
846         }
847     }
848     req->flags = flags;
849 }
850
851
852 /* cleanup a queue when a window is deleted */
853 DECL_HANDLER(cleanup_window_queue)
854 {
855     if (current->queue) cleanup_window( current->queue, req->win );
856 }
857
858
859 /* set a window timer */
860 DECL_HANDLER(set_win_timer)
861 {
862     struct timer *timer;
863     struct msg_queue *queue = get_current_queue();
864
865     if (!queue) return;
866
867     /* remove it if it existed already */
868     if (req->win) kill_timer( queue, req->win, req->msg, req->id );
869
870     if ((timer = set_timer( queue, req->rate )))
871     {
872         timer->win    = req->win;
873         timer->msg    = req->msg;
874         timer->id     = req->id;
875         timer->lparam = req->lparam;
876     }
877 }
878
879 /* kill a window timer */
880 DECL_HANDLER(kill_win_timer)
881 {
882     struct msg_queue *queue = current->queue;
883
884     if (!queue || !kill_timer( queue, req->win, req->msg, req->id ))
885         set_error( STATUS_INVALID_PARAMETER );
886 }