Let the console renderer be defined as a thread.
[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 #include "user.h"
20
21 enum message_kind { SEND_MESSAGE, POST_MESSAGE, COOKED_HW_MESSAGE, RAW_HW_MESSAGE };
22 #define NB_MSG_KINDS (RAW_HW_MESSAGE+1)
23
24
25 struct message_result
26 {
27     struct message_result *send_next;   /* next in sender list */
28     struct message_result *recv_next;   /* next in receiver list */
29     struct msg_queue      *sender;      /* sender queue */
30     struct msg_queue      *receiver;    /* receiver queue */
31     int                    replied;     /* has it been replied to? */
32     unsigned int           result;      /* reply result */
33     unsigned int           error;       /* error code to pass back to sender */
34     void                  *data;        /* message reply data */
35     unsigned int           data_size;   /* size of message reply data */
36     struct timeout_user   *timeout;     /* result timeout */
37 };
38
39 struct message
40 {
41     struct message        *next;      /* next message in list */
42     struct message        *prev;      /* prev message in list */
43     enum message_type      type;      /* message type */
44     user_handle_t          win;       /* window handle */
45     unsigned int           msg;       /* message code */
46     unsigned int           wparam;    /* parameters */
47     unsigned int           lparam;    /* parameters */
48     int                    x;         /* x position */
49     int                    y;         /* y position */
50     unsigned int           time;      /* message time */
51     unsigned int           info;      /* extra info */
52     void                  *data;      /* message data for sent messages */
53     unsigned int           data_size; /* size of message data */
54     struct message_result *result;    /* result in sender queue */
55 };
56
57 struct message_list
58 {
59     struct message *first;     /* head of list */
60     struct message *last;      /* tail of list */
61 };
62
63 struct timer
64 {
65     struct timer   *next;      /* next timer in list */
66     struct timer   *prev;      /* prev timer in list */
67     struct timeval  when;      /* next expiration */
68     unsigned int    rate;      /* timer rate in ms */
69     user_handle_t   win;       /* window handle */
70     unsigned int    msg;       /* message to post */
71     unsigned int    id;        /* timer id */
72     unsigned int    lparam;    /* lparam for message */
73 };
74
75 struct msg_queue
76 {
77     struct object          obj;           /* object header */
78     unsigned int           wake_bits;     /* wakeup bits */
79     unsigned int           wake_mask;     /* wakeup mask */
80     unsigned int           changed_bits;  /* changed wakeup bits */
81     unsigned int           changed_mask;  /* changed wakeup mask */
82     int                    paint_count;   /* pending paint messages count */
83     struct message_list    msg_list[NB_MSG_KINDS];  /* lists of messages */
84     struct message_result *send_result;   /* stack of sent messages waiting for result */
85     struct message_result *recv_result;   /* stack of received messages waiting for result */
86     struct message        *last_msg;      /* last msg returned to the app and not removed */
87     enum message_kind      last_msg_kind; /* message kind of last_msg */
88     struct timer          *first_timer;   /* head of timer list */
89     struct timer          *last_timer;    /* tail of timer list */
90     struct timer          *next_timer;    /* next timer to expire */
91     struct timeout_user   *timeout;       /* timeout for next timer to expire */
92 };
93
94 static void msg_queue_dump( struct object *obj, int verbose );
95 static int msg_queue_add_queue( struct object *obj, struct wait_queue_entry *entry );
96 static void msg_queue_remove_queue( struct object *obj, struct wait_queue_entry *entry );
97 static int msg_queue_signaled( struct object *obj, struct thread *thread );
98 static int msg_queue_satisfied( struct object *obj, struct thread *thread );
99 static void msg_queue_destroy( struct object *obj );
100 static void timer_callback( void *private );
101
102 static const struct object_ops msg_queue_ops =
103 {
104     sizeof(struct msg_queue),  /* size */
105     msg_queue_dump,            /* dump */
106     msg_queue_add_queue,       /* add_queue */
107     msg_queue_remove_queue,    /* remove_queue */
108     msg_queue_signaled,        /* signaled */
109     msg_queue_satisfied,       /* satisfied */
110     NULL,                      /* get_poll_events */
111     NULL,                      /* poll_event */
112     no_get_fd,                 /* get_fd */
113     no_flush,                  /* flush */
114     no_get_file_info,          /* get_file_info */
115     msg_queue_destroy          /* destroy */
116 };
117
118
119 static struct msg_queue *create_msg_queue( struct thread *thread )
120 {
121     struct msg_queue *queue;
122     int i;
123
124     if ((queue = alloc_object( &msg_queue_ops, -1 )))
125     {
126         queue->wake_bits       = 0;
127         queue->wake_mask       = 0;
128         queue->changed_bits    = 0;
129         queue->changed_mask    = 0;
130         queue->paint_count     = 0;
131         queue->send_result     = NULL;
132         queue->recv_result     = NULL;
133         queue->last_msg        = NULL;
134         queue->first_timer     = NULL;
135         queue->last_timer      = NULL;
136         queue->next_timer      = NULL;
137         queue->timeout         = NULL;
138         for (i = 0; i < NB_MSG_KINDS; i++)
139             queue->msg_list[i].first = queue->msg_list[i].last = NULL;
140
141         thread->queue = queue;
142         if (!thread->process->queue)
143             thread->process->queue = (struct msg_queue *)grab_object( queue );
144     }
145     return queue;
146 }
147
148 /* check the queue status */
149 inline static int is_signaled( struct msg_queue *queue )
150 {
151     return ((queue->wake_bits & queue->wake_mask) || (queue->changed_bits & queue->changed_mask));
152 }
153
154 /* set some queue bits */
155 inline static void set_queue_bits( struct msg_queue *queue, unsigned int bits )
156 {
157     queue->wake_bits |= bits;
158     queue->changed_bits |= bits;
159     if (is_signaled( queue )) wake_up( &queue->obj, 0 );
160 }
161
162 /* clear some queue bits */
163 inline static void clear_queue_bits( struct msg_queue *queue, unsigned int bits )
164 {
165     queue->wake_bits &= ~bits;
166     queue->changed_bits &= ~bits;
167 }
168
169 /* get the QS_* bit corresponding to a given hardware message */
170 inline static int get_hardware_msg_bit( struct message *msg )
171 {
172     if (msg->msg == WM_MOUSEMOVE || msg->msg == WM_NCMOUSEMOVE) return QS_MOUSEMOVE;
173     if (msg->msg >= WM_KEYFIRST && msg->msg <= WM_KEYLAST) return QS_KEY;
174     return QS_MOUSEBUTTON;
175 }
176
177 /* get the current thread queue, creating it if needed */
178 inline static struct msg_queue *get_current_queue(void)
179 {
180     struct msg_queue *queue = current->queue;
181     if (!queue) queue = create_msg_queue( current );
182     return queue;
183 }
184
185 /* append a message to the end of a list */
186 inline static void append_message( struct message_list *list, struct message *msg )
187 {
188     msg->next = NULL;
189     if ((msg->prev = list->last)) msg->prev->next = msg;
190     else list->first = msg;
191     list->last = msg;
192 }
193
194 /* unlink a message from a list it */
195 inline static void unlink_message( struct message_list *list, struct message *msg )
196 {
197     if (msg->next) msg->next->prev = msg->prev;
198     else list->last = msg->prev;
199     if (msg->prev) msg->prev->next = msg->next;
200     else list->first = msg->next;
201 }
202
203 /* try to merge a message with the last in the list; return 1 if successful */
204 static int merge_message( struct message_list *list, const struct message *msg )
205 {
206     struct message *prev = list->last;
207
208     if (!prev) return 0;
209     if (prev->result) return 0;
210     if (prev->win != msg->win) return 0;
211     if (prev->msg != msg->msg) return 0;
212     if (prev->type != msg->type) return 0;
213     /* now we can merge it */
214     prev->wparam  = msg->wparam;
215     prev->lparam  = msg->lparam;
216     prev->x       = msg->x;
217     prev->y       = msg->y;
218     prev->time    = msg->time;
219     prev->info    = msg->info;
220     return 1;
221 }
222
223 /* free a result structure */
224 static void free_result( struct message_result *result )
225 {
226     if (result->timeout) remove_timeout_user( result->timeout );
227     if (result->data) free( result->data );
228     free( result );
229 }
230
231 /* store the message result in the appropriate structure */
232 static void store_message_result( struct message_result *res, unsigned int result,
233                                   unsigned int error )
234 {
235     res->result  = result;
236     res->error   = error;
237     res->replied = 1;
238     if (res->timeout)
239     {
240         remove_timeout_user( res->timeout );
241         res->timeout = NULL;
242     }
243     /* wake sender queue if waiting on this result */
244     if (res->sender && res->sender->send_result == res)
245         set_queue_bits( res->sender, QS_SMRESULT );
246 }
247
248 /* free a message when deleting a queue or window */
249 static void free_message( struct message *msg )
250 {
251     struct message_result *result = msg->result;
252     if (result)
253     {
254         if (result->sender)
255         {
256             result->receiver = NULL;
257             store_message_result( result, 0, STATUS_ACCESS_DENIED /*FIXME*/ );
258         }
259         else free_result( result );
260     }
261     if (msg->data) free( msg->data );
262     free( msg );
263 }
264
265 /* remove (and free) a message from a message list */
266 static void remove_queue_message( struct msg_queue *queue, struct message *msg,
267                                   enum message_kind kind )
268 {
269     int clr_bit;
270     struct message *other;
271
272     if (queue->last_msg == msg) queue->last_msg = NULL;
273     unlink_message( &queue->msg_list[kind], msg );
274     switch(kind)
275     {
276     case SEND_MESSAGE:
277         if (!queue->msg_list[kind].first) clear_queue_bits( queue, QS_SENDMESSAGE );
278         break;
279     case POST_MESSAGE:
280         if (!queue->msg_list[kind].first) clear_queue_bits( queue, QS_POSTMESSAGE );
281         break;
282     case COOKED_HW_MESSAGE:
283     case RAW_HW_MESSAGE:
284         clr_bit = get_hardware_msg_bit( msg );
285         for (other = queue->msg_list[kind].first; other; other = other->next)
286             if (get_hardware_msg_bit( other ) == clr_bit) break;
287         if (!other) clear_queue_bits( queue, clr_bit );
288         break;
289     }
290     free_message( msg );
291 }
292
293 /* message timed out without getting a reply */
294 static void result_timeout( void *private )
295 {
296     struct message_result *result = private;
297
298     assert( !result->replied );
299
300     result->timeout = NULL;
301     store_message_result( result, 0, STATUS_TIMEOUT );
302 }
303
304 /* allocate and fill a message result structure */
305 static struct message_result *alloc_message_result( struct msg_queue *send_queue,
306                                                     struct msg_queue *recv_queue,
307                                                     unsigned int timeout )
308 {
309     struct message_result *result = mem_alloc( sizeof(*result) );
310     if (result)
311     {
312         /* put the result on the sender result stack */
313         result->sender    = send_queue;
314         result->receiver  = recv_queue;
315         result->replied   = 0;
316         result->data      = NULL;
317         result->data_size = 0;
318         result->timeout   = NULL;
319         result->send_next = send_queue->send_result;
320         send_queue->send_result = result;
321         if (timeout != -1)
322         {
323             struct timeval when;
324             gettimeofday( &when, 0 );
325             add_timeout( &when, timeout );
326             result->timeout = add_timeout_user( &when, result_timeout, result );
327         }
328     }
329     return result;
330 }
331
332 /* receive a message, removing it from the sent queue */
333 static void receive_message( struct msg_queue *queue, struct message *msg,
334                              struct get_message_reply *reply )
335 {
336     struct message_result *result = msg->result;
337
338     reply->total = msg->data_size;
339     if (msg->data_size > get_reply_max_size())
340     {
341         set_error( STATUS_BUFFER_OVERFLOW );
342         return;
343     }
344     reply->type   = msg->type;
345     reply->win    = msg->win;
346     reply->msg    = msg->msg;
347     reply->wparam = msg->wparam;
348     reply->lparam = msg->lparam;
349     reply->x      = msg->x;
350     reply->y      = msg->y;
351     reply->time   = msg->time;
352     reply->info   = msg->info;
353
354     if (msg->data) set_reply_data_ptr( msg->data, msg->data_size );
355
356     unlink_message( &queue->msg_list[SEND_MESSAGE], msg );
357     /* put the result on the receiver result stack */
358     if (result)
359     {
360         result->recv_next  = queue->recv_result;
361         queue->recv_result = result;
362     }
363     free( msg );
364     if (!queue->msg_list[SEND_MESSAGE].first) clear_queue_bits( queue, QS_SENDMESSAGE );
365 }
366
367 /* set the result of the current received message */
368 static void reply_message( struct msg_queue *queue, unsigned int result,
369                            unsigned int error, int remove, const void *data, size_t len )
370 {
371     struct message_result *res = queue->recv_result;
372
373     if (remove)
374     {
375         queue->recv_result = res->recv_next;
376         res->receiver = NULL;
377         if (!res->sender)  /* no one waiting for it */
378         {
379             free_result( res );
380             return;
381         }
382     }
383     if (!res->replied)
384     {
385         if (len && (res->data = memdup( data, len ))) res->data_size = len;
386         store_message_result( res, result, error );
387     }
388 }
389
390 /* empty a message list and free all the messages */
391 static void empty_msg_list( struct message_list *list )
392 {
393     struct message *msg = list->first;
394     while (msg)
395     {
396         struct message *next = msg->next;
397         free_message( msg );
398         msg = next;
399     }
400 }
401
402 /* cleanup all pending results when deleting a queue */
403 static void cleanup_results( struct msg_queue *queue )
404 {
405     struct message_result *result, *next;
406
407     result = queue->send_result;
408     while (result)
409     {
410         next = result->send_next;
411         result->sender = NULL;
412         if (!result->receiver) free_result( result );
413         result = next;
414     }
415
416     while (queue->recv_result)
417         reply_message( queue, 0, STATUS_ACCESS_DENIED /*FIXME*/, 1, NULL, 0 );
418 }
419
420 static int msg_queue_add_queue( struct object *obj, struct wait_queue_entry *entry )
421 {
422     struct msg_queue *queue = (struct msg_queue *)obj;
423     struct process *process = entry->thread->process;
424
425     /* a thread can only wait on its own queue */
426     if (entry->thread->queue != queue)
427     {
428         set_error( STATUS_ACCESS_DENIED );
429         return 0;
430     }
431     /* if waiting on the main process queue, set the idle event */
432     if (process->queue == queue)
433     {
434         if (process->idle_event) set_event( process->idle_event );
435     }
436     add_queue( obj, entry );
437     return 1;
438 }
439
440 static void msg_queue_remove_queue(struct object *obj, struct wait_queue_entry *entry )
441 {
442     struct msg_queue *queue = (struct msg_queue *)obj;
443     struct process *process = entry->thread->process;
444
445     remove_queue( obj, entry );
446
447     assert( entry->thread->queue == queue );
448
449     /* if waiting on the main process queue, reset the idle event */
450     if (process->queue == queue)
451     {
452         if (process->idle_event) reset_event( process->idle_event );
453     }
454 }
455
456 static void msg_queue_dump( struct object *obj, int verbose )
457 {
458     struct msg_queue *queue = (struct msg_queue *)obj;
459     fprintf( stderr, "Msg queue bits=%x mask=%x\n",
460              queue->wake_bits, queue->wake_mask );
461 }
462
463 static int msg_queue_signaled( struct object *obj, struct thread *thread )
464 {
465     struct msg_queue *queue = (struct msg_queue *)obj;
466     return is_signaled( queue );
467 }
468
469 static int msg_queue_satisfied( struct object *obj, struct thread *thread )
470 {
471     struct msg_queue *queue = (struct msg_queue *)obj;
472     queue->wake_mask = 0;
473     queue->changed_mask = 0;
474     return 0;  /* Not abandoned */
475 }
476
477 static void msg_queue_destroy( struct object *obj )
478 {
479     struct msg_queue *queue = (struct msg_queue *)obj;
480     struct timer *timer = queue->first_timer;
481     int i;
482
483     cleanup_results( queue );
484     for (i = 0; i < NB_MSG_KINDS; i++) empty_msg_list( &queue->msg_list[i] );
485
486     while (timer)
487     {
488         struct timer *next = timer->next;
489         free( timer );
490         timer = next;
491     }
492     if (queue->timeout) remove_timeout_user( queue->timeout );
493 }
494
495 /* set the next timer to expire */
496 static void set_next_timer( struct msg_queue *queue, struct timer *timer )
497 {
498     if (queue->timeout)
499     {
500         remove_timeout_user( queue->timeout );
501         queue->timeout = NULL;
502     }
503     if ((queue->next_timer = timer))
504         queue->timeout = add_timeout_user( &timer->when, timer_callback, queue );
505
506     /* set/clear QS_TIMER bit */
507     if (queue->next_timer == queue->first_timer)
508         clear_queue_bits( queue, QS_TIMER );
509     else
510         set_queue_bits( queue, QS_TIMER );
511 }
512
513 /* callback for the next timer expiration */
514 static void timer_callback( void *private )
515 {
516     struct msg_queue *queue = private;
517
518     queue->timeout = NULL;
519     /* move on to the next timer */
520     set_next_timer( queue, queue->next_timer->next );
521 }
522
523 /* link a timer at its rightful place in the queue list */
524 static void link_timer( struct msg_queue *queue, struct timer *timer )
525 {
526     struct timer *pos = queue->next_timer;
527
528     while (pos && time_before( &pos->when, &timer->when )) pos = pos->next;
529
530     if (pos) /* insert before pos */
531     {
532         if ((timer->prev = pos->prev)) timer->prev->next = timer;
533         else queue->first_timer = timer;
534         timer->next = pos;
535         pos->prev = timer;
536     }
537     else  /* insert at end */
538     {
539         timer->next = NULL;
540         timer->prev = queue->last_timer;
541         if (queue->last_timer) queue->last_timer->next = timer;
542         else queue->first_timer = timer;
543         queue->last_timer = timer;
544     }
545     /* check if we replaced the next timer */
546     if (pos == queue->next_timer) set_next_timer( queue, timer );
547 }
548
549 /* remove a timer from the queue timer list */
550 static void unlink_timer( struct msg_queue *queue, struct timer *timer )
551 {
552     if (timer->next) timer->next->prev = timer->prev;
553     else queue->last_timer = timer->prev;
554     if (timer->prev) timer->prev->next = timer->next;
555     else queue->first_timer = timer->next;
556     /* check if we removed the next timer */
557     if (queue->next_timer == timer) set_next_timer( queue, timer->next );
558     else if (queue->next_timer == queue->first_timer) clear_queue_bits( queue, QS_TIMER );
559 }
560
561 /* restart an expired timer */
562 static void restart_timer( struct msg_queue *queue, struct timer *timer )
563 {
564     struct timeval now;
565     unlink_timer( queue, timer );
566     gettimeofday( &now, 0 );
567     while (!time_before( &now, &timer->when )) add_timeout( &timer->when, timer->rate );
568     link_timer( queue, timer );
569 }
570
571 /* find an expired timer matching the filtering parameters */
572 static struct timer *find_expired_timer( struct msg_queue *queue, user_handle_t win,
573                                          unsigned int get_first, unsigned int get_last,
574                                          int remove )
575 {
576     struct timer *timer;
577     for (timer = queue->first_timer; (timer && timer != queue->next_timer); timer = timer->next)
578     {
579         if (win && timer->win != win) continue;
580         if (timer->msg >= get_first && timer->msg <= get_last)
581         {
582             if (remove) restart_timer( queue, timer );
583             return timer;
584         }
585     }
586     return NULL;
587 }
588
589 /* kill a timer */
590 static int kill_timer( struct msg_queue *queue, user_handle_t win,
591                        unsigned int msg, unsigned int id )
592 {
593     struct timer *timer;
594
595     for (timer = queue->first_timer; timer; timer = timer->next)
596     {
597         if (timer->win != win || timer->msg != msg || timer->id != id) continue;
598         unlink_timer( queue, timer );
599         free( timer );
600         return 1;
601     }
602     return 0;
603 }
604
605 /* add a timer */
606 static struct timer *set_timer( struct msg_queue *queue, unsigned int rate )
607 {
608     struct timer *timer = mem_alloc( sizeof(*timer) );
609     if (timer)
610     {
611         timer->rate  = rate;
612         gettimeofday( &timer->when, 0 );
613         add_timeout( &timer->when, rate );
614         link_timer( queue, timer );
615     }
616     return timer;
617 }
618
619
620 /* increment (or decrement if 'incr' is negative) the queue paint count */
621 void inc_queue_paint_count( struct thread *thread, int incr )
622 {
623     struct msg_queue *queue = thread->queue;
624
625     assert( queue );
626
627     if ((queue->paint_count += incr) < 0) queue->paint_count = 0;
628
629     if (queue->paint_count)
630         set_queue_bits( queue, QS_PAINT );
631     else
632         clear_queue_bits( queue, QS_PAINT );
633 }
634
635
636 /* remove all messages and timers belonging to a certain window */
637 void queue_cleanup_window( struct thread *thread, user_handle_t win )
638 {
639     struct msg_queue *queue = thread->queue;
640     struct timer *timer;
641     struct message *msg;
642     int i;
643
644     if (!queue) return;
645
646     /* remove timers */
647     timer = queue->first_timer;
648     while (timer)
649     {
650         struct timer *next = timer->next;
651         if (timer->win == win)
652         {
653             unlink_timer( queue, timer );
654             free( timer );
655         }
656         timer = next;
657     }
658
659     /* remove messages */
660     for (i = 0; i < NB_MSG_KINDS; i++)
661     {
662         msg = queue->msg_list[i].first;
663         while (msg)
664         {
665             struct message *next = msg->next;
666             if (msg->win == win) remove_queue_message( queue, msg, i );
667             msg = next;
668         }
669     }
670 }
671
672 /* get the message queue of the current thread */
673 DECL_HANDLER(get_msg_queue)
674 {
675     struct msg_queue *queue = get_current_queue();
676
677     reply->handle = 0;
678     if (queue) reply->handle = alloc_handle( current->process, queue, SYNCHRONIZE, 0 );
679 }
680
681
682 /* set the current message queue wakeup mask */
683 DECL_HANDLER(set_queue_mask)
684 {
685     struct msg_queue *queue = get_current_queue();
686
687     if (queue)
688     {
689         queue->wake_mask    = req->wake_mask;
690         queue->changed_mask = req->changed_mask;
691         reply->wake_bits    = queue->wake_bits;
692         reply->changed_bits = queue->changed_bits;
693         if (is_signaled( queue ))
694         {
695             /* if skip wait is set, do what would have been done in the subsequent wait */
696             if (req->skip_wait) msg_queue_satisfied( &queue->obj, current );
697             else wake_up( &queue->obj, 0 );
698         }
699     }
700 }
701
702
703 /* get the current message queue status */
704 DECL_HANDLER(get_queue_status)
705 {
706     struct msg_queue *queue = current->queue;
707     if (queue)
708     {
709         reply->wake_bits    = queue->wake_bits;
710         reply->changed_bits = queue->changed_bits;
711         if (req->clear) queue->changed_bits = 0;
712     }
713     else reply->wake_bits = reply->changed_bits = 0;
714 }
715
716
717 /* send a message to a thread queue */
718 DECL_HANDLER(send_message)
719 {
720     struct message *msg;
721     struct msg_queue *send_queue = get_current_queue();
722     struct msg_queue *recv_queue;
723     struct thread *thread = get_thread_from_id( req->id );
724
725     if (!thread) return;
726
727     if (!(recv_queue = thread->queue))
728     {
729         set_error( STATUS_INVALID_PARAMETER );
730         release_object( thread );
731         return;
732     }
733
734     if ((msg = mem_alloc( sizeof(*msg) )))
735     {
736         msg->type      = req->type;
737         msg->win       = get_user_full_handle( req->win );
738         msg->msg       = req->msg;
739         msg->wparam    = req->wparam;
740         msg->lparam    = req->lparam;
741         msg->time      = req->time;
742         msg->x         = req->x;
743         msg->y         = req->y;
744         msg->info      = req->info;
745         msg->result    = NULL;
746         msg->data      = NULL;
747         msg->data_size = 0;
748
749         switch(msg->type)
750         {
751        case MSG_OTHER_PROCESS:
752             msg->data_size = get_req_data_size();
753             if (msg->data_size && !(msg->data = memdup( get_req_data(), msg->data_size )))
754             {
755                 free( msg );
756                 break;
757             }
758             /* fall through */
759         case MSG_ASCII:
760         case MSG_UNICODE:
761         case MSG_CALLBACK:
762             if (!(msg->result = alloc_message_result( send_queue, recv_queue, req->timeout )))
763             {
764                 free( msg );
765                 break;
766             }
767             /* fall through */
768         case MSG_NOTIFY:
769             append_message( &recv_queue->msg_list[SEND_MESSAGE], msg );
770             set_queue_bits( recv_queue, QS_SENDMESSAGE );
771             break;
772         case MSG_POSTED:
773             append_message( &recv_queue->msg_list[POST_MESSAGE], msg );
774             set_queue_bits( recv_queue, QS_POSTMESSAGE );
775             break;
776         case MSG_HARDWARE_RAW:
777         case MSG_HARDWARE_COOKED:
778             {
779                 struct message_list *list = ((msg->type == MSG_HARDWARE_RAW) ?
780                                              &recv_queue->msg_list[RAW_HW_MESSAGE] :
781                                              &recv_queue->msg_list[COOKED_HW_MESSAGE]);
782                 if (msg->msg == WM_MOUSEMOVE && merge_message( list, msg ))
783                 {
784                     free( msg );
785                     break;
786                 }
787                 append_message( list, msg );
788                 set_queue_bits( recv_queue, get_hardware_msg_bit(msg) );
789                 break;
790             }
791         default:
792             set_error( STATUS_INVALID_PARAMETER );
793             free( msg );
794             break;
795         }
796     }
797     release_object( thread );
798 }
799
800 /* return a message to the application, removing it from the queue if needed */
801 static void return_message_to_app( struct msg_queue *queue, int flags,
802                                    struct get_message_reply *reply,
803                                    struct message *msg, enum message_kind kind )
804 {
805     assert( !msg->data_size );  /* posted messages can't have data */
806
807     reply->type   = msg->type;
808     reply->win    = msg->win;
809     reply->msg    = msg->msg;
810     reply->wparam = msg->wparam;
811     reply->lparam = msg->lparam;
812     reply->x      = msg->x;
813     reply->y      = msg->y;
814     reply->time   = msg->time;
815     reply->info   = msg->info;
816     reply->total  = 0;
817
818     /* raw messages always get removed */
819     if ((msg->type == MSG_HARDWARE_RAW) || (flags & GET_MSG_REMOVE))
820     {
821         queue->last_msg = NULL;
822         remove_queue_message( queue, msg, kind );
823     }
824     else  /* remember it as the last returned message */
825     {
826         queue->last_msg = msg;
827         queue->last_msg_kind = kind;
828     }
829 }
830
831
832 inline static struct message *find_matching_message( const struct message_list *list,
833                                                      user_handle_t win,
834                                                      unsigned int first, unsigned int last )
835 {
836     struct message *msg;
837
838     for (msg = list->first; msg; msg = msg->next)
839     {
840         /* check against the filters */
841         if (msg->msg == WM_QUIT) break;  /* WM_QUIT is never filtered */
842         if (win && msg->win && msg->win != win && !is_child_window( win, msg->win )) continue;
843         if (msg->msg < first) continue;
844         if (msg->msg > last) continue;
845         break; /* found one */
846     }
847     return msg;
848 }
849
850
851 /* get a message from the current queue */
852 DECL_HANDLER(get_message)
853 {
854     struct timer *timer;
855     struct message *msg;
856     struct msg_queue *queue = get_current_queue();
857     user_handle_t get_win = get_user_full_handle( req->get_win );
858
859     if (!queue) return;
860
861     /* first check for sent messages */
862     if ((msg = queue->msg_list[SEND_MESSAGE].first))
863     {
864         receive_message( queue, msg, reply );
865         return;
866     }
867     if (req->flags & GET_MSG_SENT_ONLY) goto done;  /* nothing else to check */
868
869     /* if requested, remove the last returned but not yet removed message */
870     if ((req->flags & GET_MSG_REMOVE_LAST) && queue->last_msg)
871         remove_queue_message( queue, queue->last_msg, queue->last_msg_kind );
872     queue->last_msg = NULL;
873
874     /* clear changed bits so we can wait on them if we don't find a message */
875     queue->changed_bits = 0;
876
877     /* then check for posted messages */
878     if ((msg = find_matching_message( &queue->msg_list[POST_MESSAGE], get_win,
879                                       req->get_first, req->get_last )))
880     {
881         return_message_to_app( queue, req->flags, reply, msg, POST_MESSAGE );
882         return;
883     }
884
885     /* then check for cooked hardware messages */
886     if ((msg = find_matching_message( &queue->msg_list[COOKED_HW_MESSAGE], get_win,
887                                       req->get_first, req->get_last )))
888     {
889         return_message_to_app( queue, req->flags, reply, msg, COOKED_HW_MESSAGE );
890         return;
891     }
892
893     /* then check for any raw hardware message */
894     if ((msg = queue->msg_list[RAW_HW_MESSAGE].first))
895     {
896         return_message_to_app( queue, req->flags, reply, msg, RAW_HW_MESSAGE );
897         return;
898     }
899
900     /* now check for WM_PAINT */
901     if (queue->paint_count &&
902         (WM_PAINT >= req->get_first) && (WM_PAINT <= req->get_last) &&
903         (reply->win = find_window_to_repaint( get_win, current )))
904     {
905         reply->type   = MSG_POSTED;
906         reply->msg    = WM_PAINT;
907         reply->wparam = 0;
908         reply->lparam = 0;
909         reply->x      = 0;
910         reply->y      = 0;
911         reply->time   = get_tick_count();
912         reply->info   = 0;
913         return;
914     }
915
916     /* now check for timer */
917     if ((timer = find_expired_timer( queue, get_win, req->get_first,
918                                      req->get_last, (req->flags & GET_MSG_REMOVE) )))
919     {
920         reply->type   = MSG_POSTED;
921         reply->win    = timer->win;
922         reply->msg    = timer->msg;
923         reply->wparam = timer->id;
924         reply->lparam = timer->lparam;
925         reply->x      = 0;
926         reply->y      = 0;
927         reply->time   = get_tick_count();
928         reply->info   = 0;
929         return;
930     }
931
932  done:
933     set_error( STATUS_PENDING );  /* FIXME */
934 }
935
936
937 /* reply to a sent message */
938 DECL_HANDLER(reply_message)
939 {
940     if (current->queue && current->queue->recv_result)
941         reply_message( current->queue, req->result, 0, req->remove,
942                        get_req_data(), get_req_data_size() );
943     else
944         set_error( STATUS_ACCESS_DENIED );
945 }
946
947
948 /* retrieve the reply for the last message sent */
949 DECL_HANDLER(get_message_reply)
950 {
951     struct msg_queue *queue = current->queue;
952
953     if (queue)
954     {
955         struct message_result *result = queue->send_result;
956
957         set_error( STATUS_PENDING );
958         reply->result = 0;
959
960         if (result && (result->replied || req->cancel))
961         {
962             if (result->replied)
963             {
964                 reply->result = result->result;
965                 set_error( result->error );
966                 if (result->data)
967                 {
968                     size_t data_len = min( result->data_size, get_reply_max_size() );
969                     set_reply_data_ptr( result->data, data_len );
970                     result->data = NULL;
971                     result->data_size = 0;
972                 }
973             }
974             queue->send_result = result->send_next;
975             result->sender = NULL;
976             if (!result->receiver) free_result( result );
977             if (!queue->send_result || !queue->send_result->replied)
978                 clear_queue_bits( queue, QS_SMRESULT );
979         }
980     }
981     else set_error( STATUS_ACCESS_DENIED );
982 }
983
984
985 /* set a window timer */
986 DECL_HANDLER(set_win_timer)
987 {
988     struct timer *timer;
989     struct msg_queue *queue = get_current_queue();
990     user_handle_t win = get_user_full_handle( req->win );
991
992     if (!queue) return;
993
994     /* remove it if it existed already */
995     if (win) kill_timer( queue, win, req->msg, req->id );
996
997     if ((timer = set_timer( queue, req->rate )))
998     {
999         timer->win    = win;
1000         timer->msg    = req->msg;
1001         timer->id     = req->id;
1002         timer->lparam = req->lparam;
1003     }
1004 }
1005
1006 /* kill a window timer */
1007 DECL_HANDLER(kill_win_timer)
1008 {
1009     struct msg_queue *queue = current->queue;
1010
1011     if (!queue || !kill_timer( queue, get_user_full_handle(req->win), req->msg, req->id ))
1012         set_error( STATUS_INVALID_PARAMETER );
1013 }