2 * Server-side message queues
4 * Copyright (C) 2000 Alexandre Julliard
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 */
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 */
49 struct message
*first
; /* head of list */
50 struct message
*last
; /* tail of list */
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 */
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 message
*last_msg
; /* last msg returned to the app and not removed */
77 enum message_kind last_msg_kind
; /* message kind of last_msg */
78 struct timer
*first_timer
; /* head of timer list */
79 struct timer
*last_timer
; /* tail of timer list */
80 struct timer
*next_timer
; /* next timer to expire */
81 struct timeout_user
*timeout
; /* timeout for next timer to expire */
84 static void msg_queue_dump( struct object
*obj
, int verbose
);
85 static int msg_queue_add_queue( struct object
*obj
, struct wait_queue_entry
*entry
);
86 static void msg_queue_remove_queue( struct object
*obj
, struct wait_queue_entry
*entry
);
87 static int msg_queue_signaled( struct object
*obj
, struct thread
*thread
);
88 static int msg_queue_satisfied( struct object
*obj
, struct thread
*thread
);
89 static void msg_queue_destroy( struct object
*obj
);
90 static void timer_callback( void *private );
92 static const struct object_ops msg_queue_ops
=
94 sizeof(struct msg_queue
), /* size */
95 msg_queue_dump
, /* dump */
96 msg_queue_add_queue
, /* add_queue */
97 msg_queue_remove_queue
, /* remove_queue */
98 msg_queue_signaled
, /* signaled */
99 msg_queue_satisfied
, /* satisfied */
100 NULL
, /* get_poll_events */
101 NULL
, /* poll_event */
102 no_get_fd
, /* get_fd */
103 no_flush
, /* flush */
104 no_get_file_info
, /* get_file_info */
105 msg_queue_destroy
/* destroy */
109 static struct msg_queue
*create_msg_queue( struct thread
*thread
)
111 struct msg_queue
*queue
;
114 if ((queue
= alloc_object( &msg_queue_ops
, -1 )))
116 queue
->wake_bits
= 0;
117 queue
->wake_mask
= 0;
118 queue
->changed_bits
= 0;
119 queue
->changed_mask
= 0;
120 queue
->paint_count
= 0;
121 queue
->send_result
= NULL
;
122 queue
->recv_result
= NULL
;
123 queue
->last_msg
= NULL
;
124 queue
->first_timer
= NULL
;
125 queue
->last_timer
= NULL
;
126 queue
->next_timer
= NULL
;
127 queue
->timeout
= NULL
;
128 for (i
= 0; i
< NB_MSG_KINDS
; i
++)
129 queue
->msg_list
[i
].first
= queue
->msg_list
[i
].last
= NULL
;
131 thread
->queue
= queue
;
132 if (!thread
->process
->queue
)
133 thread
->process
->queue
= (struct msg_queue
*)grab_object( queue
);
138 /* check the queue status */
139 inline static int is_signaled( struct msg_queue
*queue
)
141 return ((queue
->wake_bits
& queue
->wake_mask
) || (queue
->changed_bits
& queue
->changed_mask
));
144 /* set/clear some queue bits */
145 inline static void change_queue_bits( struct msg_queue
*queue
, unsigned int set
, unsigned int clear
)
147 queue
->wake_bits
= (queue
->wake_bits
| set
) & ~clear
;
148 queue
->changed_bits
= (queue
->changed_bits
| set
) & ~clear
;
149 if (is_signaled( queue
)) wake_up( &queue
->obj
, 0 );
152 /* get the QS_* bit corresponding to a given hardware message */
153 inline static int get_hardware_msg_bit( struct message
*msg
)
155 if (msg
->msg
== WM_MOUSEMOVE
|| msg
->msg
== WM_NCMOUSEMOVE
) return QS_MOUSEMOVE
;
156 if (msg
->msg
>= WM_KEYFIRST
&& msg
->msg
<= WM_KEYLAST
) return QS_KEY
;
157 return QS_MOUSEBUTTON
;
160 /* get the current thread queue, creating it if needed */
161 inline struct msg_queue
*get_current_queue(void)
163 struct msg_queue
*queue
= current
->queue
;
164 if (!queue
) queue
= create_msg_queue( current
);
168 /* append a message to the end of a list */
169 inline static void append_message( struct message_list
*list
, struct message
*msg
)
172 if ((msg
->prev
= list
->last
)) msg
->prev
->next
= msg
;
173 else list
->first
= msg
;
177 /* unlink a message from a list it */
178 inline static void unlink_message( struct message_list
*list
, struct message
*msg
)
180 if (msg
->next
) msg
->next
->prev
= msg
->prev
;
181 else list
->last
= msg
->prev
;
182 if (msg
->prev
) msg
->prev
->next
= msg
->next
;
183 else list
->first
= msg
->next
;
186 /* try to merge a message with the last in the list; return 1 if successful */
187 static int merge_message( struct message_list
*list
, const struct message
*msg
)
189 struct message
*prev
= list
->last
;
192 if (prev
->result
) return 0;
193 if (prev
->win
!= msg
->win
) return 0;
194 if (prev
->msg
!= msg
->msg
) return 0;
195 if (prev
->type
!= msg
->type
) return 0;
196 /* now we can merge it */
197 prev
->wparam
= msg
->wparam
;
198 prev
->lparam
= msg
->lparam
;
201 prev
->time
= msg
->time
;
202 prev
->info
= msg
->info
;
206 /* free a message when deleting a queue or window */
207 static void free_message( struct message
*msg
)
209 struct message_result
*result
= msg
->result
;
215 result
->error
= STATUS_ACCESS_DENIED
; /* FIXME */
217 result
->receiver
= NULL
;
218 /* wake sender queue if waiting on this result */
219 if (result
->sender
->send_result
== result
)
220 change_queue_bits( result
->sender
, QS_SMRESULT
, 0 );
227 /* remove (and free) a message from a message list */
228 static void remove_queue_message( struct msg_queue
*queue
, struct message
*msg
,
229 enum message_kind kind
)
232 struct message
*other
;
234 if (queue
->last_msg
== msg
) queue
->last_msg
= NULL
;
235 unlink_message( &queue
->msg_list
[kind
], msg
);
239 if (!queue
->msg_list
[kind
].first
) change_queue_bits( queue
, 0, QS_SENDMESSAGE
);
242 if (!queue
->msg_list
[kind
].first
) change_queue_bits( queue
, 0, QS_POSTMESSAGE
);
244 case COOKED_HW_MESSAGE
:
246 clr_bit
= get_hardware_msg_bit( msg
);
247 for (other
= queue
->msg_list
[kind
].first
; other
; other
= other
->next
)
248 if (get_hardware_msg_bit( other
) == clr_bit
) break;
249 if (!other
) change_queue_bits( queue
, 0, clr_bit
);
255 /* send a message from the sender queue to the receiver queue */
256 static int send_message( struct msg_queue
*send_queue
, struct msg_queue
*recv_queue
,
257 struct message
*msg
)
259 struct message_result
*result
= mem_alloc( sizeof(*result
) );
260 if (!result
) return 0;
262 /* put the result on the sender result stack */
263 result
->sender
= send_queue
;
264 result
->receiver
= recv_queue
;
266 result
->send_next
= send_queue
->send_result
;
267 send_queue
->send_result
= result
;
269 /* and put the message on the receiver queue */
270 msg
->result
= result
;
271 append_message( &recv_queue
->msg_list
[SEND_MESSAGE
], msg
);
272 change_queue_bits( recv_queue
, QS_SENDMESSAGE
, 0 );
276 /* receive a message, removing it from the sent queue */
277 static void receive_message( struct msg_queue
*queue
, struct message
*msg
)
279 struct message_result
*result
= msg
->result
;
281 unlink_message( &queue
->msg_list
[SEND_MESSAGE
], msg
);
282 /* put the result on the receiver result stack */
283 result
->recv_next
= queue
->recv_result
;
284 queue
->recv_result
= result
;
286 if (!queue
->msg_list
[SEND_MESSAGE
].first
) change_queue_bits( queue
, 0, QS_SENDMESSAGE
);
289 /* set the result of the current received message */
290 static void reply_message( struct msg_queue
*queue
, unsigned int result
,
291 unsigned int error
, int remove
)
293 struct message_result
*res
= queue
->recv_result
;
297 queue
->recv_result
= res
->recv_next
;
298 res
->receiver
= NULL
;
299 if (!res
->sender
) /* no one waiting for it */
307 res
->result
= result
;
310 /* wake sender queue if waiting on this result */
311 if (res
->sender
&& res
->sender
->send_result
== res
)
312 change_queue_bits( res
->sender
, QS_SMRESULT
, 0 );
316 /* retrieve the reply of the current message being sent */
317 static unsigned int get_message_reply( struct msg_queue
*queue
, int cancel
)
319 struct message_result
*res
= queue
->send_result
;
320 unsigned int ret
= 0;
322 set_error( STATUS_PENDING
);
324 if (res
&& (res
->replied
|| cancel
))
329 set_error( res
->error
);
331 queue
->send_result
= res
->send_next
;
333 if (!res
->receiver
) free( res
);
334 if (!queue
->send_result
|| !queue
->send_result
->replied
)
335 change_queue_bits( queue
, 0, QS_SMRESULT
);
340 /* empty a message list and free all the messages */
341 static void empty_msg_list( struct message_list
*list
)
343 struct message
*msg
= list
->first
;
346 struct message
*next
= msg
->next
;
352 /* cleanup all pending results when deleting a queue */
353 static void cleanup_results( struct msg_queue
*queue
)
355 struct message_result
*result
, *next
;
357 result
= queue
->send_result
;
360 next
= result
->send_next
;
361 result
->sender
= NULL
;
362 if (!result
->receiver
) free( result
);
366 while (queue
->recv_result
) reply_message( queue
, 0, STATUS_ACCESS_DENIED
/*FIXME*/, 1 );
369 static int msg_queue_add_queue( struct object
*obj
, struct wait_queue_entry
*entry
)
371 struct msg_queue
*queue
= (struct msg_queue
*)obj
;
372 struct process
*process
= entry
->thread
->process
;
374 /* a thread can only wait on its own queue */
375 if (entry
->thread
->queue
!= queue
)
377 set_error( STATUS_ACCESS_DENIED
);
380 /* if waiting on the main process queue, set the idle event */
381 if (process
->queue
== queue
)
383 if (process
->idle_event
) set_event( process
->idle_event
);
385 add_queue( obj
, entry
);
389 static void msg_queue_remove_queue(struct object
*obj
, struct wait_queue_entry
*entry
)
391 struct msg_queue
*queue
= (struct msg_queue
*)obj
;
392 struct process
*process
= entry
->thread
->process
;
394 remove_queue( obj
, entry
);
396 assert( entry
->thread
->queue
== queue
);
398 /* if waiting on the main process queue, reset the idle event */
399 if (process
->queue
== queue
)
401 if (process
->idle_event
) reset_event( process
->idle_event
);
405 static void msg_queue_dump( struct object
*obj
, int verbose
)
407 struct msg_queue
*queue
= (struct msg_queue
*)obj
;
408 fprintf( stderr
, "Msg queue bits=%x mask=%x\n",
409 queue
->wake_bits
, queue
->wake_mask
);
412 static int msg_queue_signaled( struct object
*obj
, struct thread
*thread
)
414 struct msg_queue
*queue
= (struct msg_queue
*)obj
;
415 return is_signaled( queue
);
418 static int msg_queue_satisfied( struct object
*obj
, struct thread
*thread
)
420 struct msg_queue
*queue
= (struct msg_queue
*)obj
;
421 queue
->wake_mask
= 0;
422 queue
->changed_mask
= 0;
423 return 0; /* Not abandoned */
426 static void msg_queue_destroy( struct object
*obj
)
428 struct msg_queue
*queue
= (struct msg_queue
*)obj
;
429 struct timer
*timer
= queue
->first_timer
;
432 cleanup_results( queue
);
433 for (i
= 0; i
< NB_MSG_KINDS
; i
++) empty_msg_list( &queue
->msg_list
[i
] );
437 struct timer
*next
= timer
->next
;
441 if (queue
->timeout
) remove_timeout_user( queue
->timeout
);
444 /* set the next timer to expire */
445 static void set_next_timer( struct msg_queue
*queue
, struct timer
*timer
)
449 remove_timeout_user( queue
->timeout
);
450 queue
->timeout
= NULL
;
452 if ((queue
->next_timer
= timer
))
453 queue
->timeout
= add_timeout_user( &timer
->when
, timer_callback
, queue
);
455 /* set/clear QS_TIMER bit */
456 if (queue
->next_timer
== queue
->first_timer
)
457 change_queue_bits( queue
, 0, QS_TIMER
);
459 change_queue_bits( queue
, QS_TIMER
, 0 );
462 /* callback for the next timer expiration */
463 static void timer_callback( void *private )
465 struct msg_queue
*queue
= private;
467 queue
->timeout
= NULL
;
468 /* move on to the next timer */
469 set_next_timer( queue
, queue
->next_timer
->next
);
472 /* link a timer at its rightful place in the queue list */
473 static void link_timer( struct msg_queue
*queue
, struct timer
*timer
)
475 struct timer
*pos
= queue
->next_timer
;
477 while (pos
&& time_before( &pos
->when
, &timer
->when
)) pos
= pos
->next
;
479 if (pos
) /* insert before pos */
481 if ((timer
->prev
= pos
->prev
)) timer
->prev
->next
= timer
;
482 else queue
->first_timer
= timer
;
486 else /* insert at end */
489 timer
->prev
= queue
->last_timer
;
490 if (queue
->last_timer
) queue
->last_timer
->next
= timer
;
491 else queue
->first_timer
= timer
;
492 queue
->last_timer
= timer
;
494 /* check if we replaced the next timer */
495 if (pos
== queue
->next_timer
) set_next_timer( queue
, timer
);
498 /* remove a timer from the queue timer list */
499 static void unlink_timer( struct msg_queue
*queue
, struct timer
*timer
)
501 if (timer
->next
) timer
->next
->prev
= timer
->prev
;
502 else queue
->last_timer
= timer
->prev
;
503 if (timer
->prev
) timer
->prev
->next
= timer
->next
;
504 else queue
->first_timer
= timer
->next
;
505 /* check if we removed the next timer */
506 if (queue
->next_timer
== timer
) set_next_timer( queue
, timer
->next
);
507 else if (queue
->next_timer
== queue
->first_timer
) change_queue_bits( queue
, 0, QS_TIMER
);
510 /* restart an expired timer */
511 static void restart_timer( struct msg_queue
*queue
, struct timer
*timer
)
514 unlink_timer( queue
, timer
);
515 gettimeofday( &now
, 0 );
516 while (!time_before( &now
, &timer
->when
)) add_timeout( &timer
->when
, timer
->rate
);
517 link_timer( queue
, timer
);
520 /* find an expired timer matching the filtering parameters */
521 static struct timer
*find_expired_timer( struct msg_queue
*queue
, handle_t win
,
522 unsigned int get_first
, unsigned int get_last
,
526 for (timer
= queue
->first_timer
; (timer
&& timer
!= queue
->next_timer
); timer
= timer
->next
)
528 if (win
&& timer
->win
!= win
) continue;
529 if (timer
->msg
>= get_first
&& timer
->msg
<= get_last
)
531 if (remove
) restart_timer( queue
, timer
);
539 static int kill_timer( struct msg_queue
*queue
, handle_t win
, unsigned int msg
, unsigned int id
)
543 for (timer
= queue
->first_timer
; timer
; timer
= timer
->next
)
545 if (timer
->win
!= win
|| timer
->msg
!= msg
|| timer
->id
!= id
) continue;
546 unlink_timer( queue
, timer
);
554 static struct timer
*set_timer( struct msg_queue
*queue
, unsigned int rate
)
556 struct timer
*timer
= mem_alloc( sizeof(*timer
) );
560 gettimeofday( &timer
->when
, 0 );
561 add_timeout( &timer
->when
, rate
);
562 link_timer( queue
, timer
);
567 /* remove all messages and timers belonging to a certain window */
568 static void cleanup_window( struct msg_queue
*queue
, handle_t win
)
575 timer
= queue
->first_timer
;
578 struct timer
*next
= timer
->next
;
579 if (timer
->win
== win
)
581 unlink_timer( queue
, timer
);
587 /* remove messages */
588 for (i
= 0; i
< NB_MSG_KINDS
; i
++)
590 msg
= queue
->msg_list
[i
].first
;
593 struct message
*next
= msg
->next
;
594 if (msg
->win
== win
) remove_queue_message( queue
, msg
, i
);
600 /* get the message queue of the current thread */
601 DECL_HANDLER(get_msg_queue
)
603 struct msg_queue
*queue
= get_current_queue();
606 if (queue
) req
->handle
= alloc_handle( current
->process
, queue
, SYNCHRONIZE
, 0 );
610 /* increment the message queue paint count */
611 DECL_HANDLER(inc_queue_paint_count
)
613 struct msg_queue
*queue
;
614 struct thread
*thread
= get_thread_from_id( req
->id
);
618 if ((queue
= thread
->queue
))
620 if ((queue
->paint_count
+= req
->incr
) < 0) queue
->paint_count
= 0;
622 if (queue
->paint_count
)
623 change_queue_bits( queue
, QS_PAINT
, 0 );
625 change_queue_bits( queue
, 0, QS_PAINT
);
627 else set_error( STATUS_INVALID_PARAMETER
);
629 release_object( thread
);
634 /* set the current message queue wakeup mask */
635 DECL_HANDLER(set_queue_mask
)
637 struct msg_queue
*queue
= get_current_queue();
641 queue
->wake_mask
= req
->wake_mask
;
642 queue
->changed_mask
= req
->changed_mask
;
643 req
->wake_bits
= queue
->wake_bits
;
644 req
->changed_bits
= queue
->changed_bits
;
645 if (is_signaled( queue
))
647 /* if skip wait is set, do what would have been done in the subsequent wait */
648 if (req
->skip_wait
) msg_queue_satisfied( &queue
->obj
, current
);
649 else wake_up( &queue
->obj
, 0 );
655 /* get the current message queue status */
656 DECL_HANDLER(get_queue_status
)
658 struct msg_queue
*queue
= current
->queue
;
661 req
->wake_bits
= queue
->wake_bits
;
662 req
->changed_bits
= queue
->changed_bits
;
663 if (req
->clear
) queue
->changed_bits
= 0;
665 else req
->wake_bits
= req
->changed_bits
= 0;
669 /* send a message to a thread queue */
670 DECL_HANDLER(send_message
)
673 struct msg_queue
*send_queue
= get_current_queue();
674 struct msg_queue
*recv_queue
;
675 struct thread
*thread
= get_thread_from_id( req
->id
);
679 if (!(recv_queue
= thread
->queue
))
681 set_error( STATUS_INVALID_PARAMETER
);
682 release_object( thread
);
686 if ((msg
= mem_alloc( sizeof(*msg
) )))
688 msg
->type
= req
->type
;
691 msg
->wparam
= req
->wparam
;
692 msg
->lparam
= req
->lparam
;
695 msg
->time
= req
->time
;
696 msg
->info
= req
->info
;
701 send_message( send_queue
, recv_queue
, msg
);
704 append_message( &recv_queue
->msg_list
[POST_MESSAGE
], msg
);
705 change_queue_bits( recv_queue
, QS_POSTMESSAGE
, 0 );
707 case COOKED_HW_MESSAGE
:
709 if (msg
->msg
== WM_MOUSEMOVE
&& merge_message( &recv_queue
->msg_list
[req
->kind
], msg
))
715 append_message( &recv_queue
->msg_list
[req
->kind
], msg
);
716 change_queue_bits( recv_queue
, get_hardware_msg_bit(msg
), 0 );
721 set_error( STATUS_INVALID_PARAMETER
);
725 release_object( thread
);
728 /* store a message contents into the request buffer; helper for get_message */
729 inline static void put_req_message( struct get_message_request
*req
, const struct message
*msg
)
731 req
->type
= msg
->type
;
734 req
->wparam
= msg
->wparam
;
735 req
->lparam
= msg
->lparam
;
738 req
->time
= msg
->time
;
739 req
->info
= msg
->info
;
742 /* return a message to the application, removing it from the queue if needed */
743 static void return_message_to_app( struct msg_queue
*queue
, struct get_message_request
*req
,
744 struct message
*msg
, enum message_kind kind
)
747 put_req_message( req
, msg
);
748 /* raw messages always get removed */
749 if ((kind
== RAW_HW_MESSAGE
) || (req
->flags
& GET_MSG_REMOVE
))
751 queue
->last_msg
= NULL
;
752 remove_queue_message( queue
, msg
, kind
);
754 else /* remember it as the last returned message */
756 queue
->last_msg
= msg
;
757 queue
->last_msg_kind
= kind
;
762 inline static struct message
*find_matching_message( const struct message_list
*list
, handle_t win
,
763 unsigned int first
, unsigned int last
)
767 for (msg
= list
->first
; msg
; msg
= msg
->next
)
769 /* check against the filters */
770 if (msg
->msg
== WM_QUIT
) break; /* WM_QUIT is never filtered */
771 if (win
&& msg
->win
&& msg
->win
!= win
) continue;
772 if (msg
->msg
< first
) continue;
773 if (msg
->msg
> last
) continue;
774 break; /* found one */
780 /* get a message from the current queue */
781 DECL_HANDLER(get_message
)
785 struct msg_queue
*queue
= get_current_queue();
789 /* first check for sent messages */
790 if ((msg
= queue
->msg_list
[SEND_MESSAGE
].first
))
792 req
->kind
= SEND_MESSAGE
;
793 put_req_message( req
, msg
);
794 receive_message( queue
, msg
);
797 if (req
->flags
& GET_MSG_SENT_ONLY
) goto done
; /* nothing else to check */
799 /* if requested, remove the last returned but not yet removed message */
800 if ((req
->flags
& GET_MSG_REMOVE_LAST
) && queue
->last_msg
)
801 remove_queue_message( queue
, queue
->last_msg
, queue
->last_msg_kind
);
802 queue
->last_msg
= NULL
;
804 /* clear changed bits so we can wait on them if we don't find a message */
805 queue
->changed_bits
= 0;
807 /* then check for posted messages */
808 if ((msg
= find_matching_message( &queue
->msg_list
[POST_MESSAGE
], req
->get_win
,
809 req
->get_first
, req
->get_last
)))
811 return_message_to_app( queue
, req
, msg
, POST_MESSAGE
);
815 /* then check for cooked hardware messages */
816 if ((msg
= find_matching_message( &queue
->msg_list
[COOKED_HW_MESSAGE
], req
->get_win
,
817 req
->get_first
, req
->get_last
)))
819 return_message_to_app( queue
, req
, msg
, COOKED_HW_MESSAGE
);
823 /* then check for any raw hardware message */
824 if ((msg
= queue
->msg_list
[RAW_HW_MESSAGE
].first
))
826 return_message_to_app( queue
, req
, msg
, RAW_HW_MESSAGE
);
830 /* now check for WM_PAINT */
831 if ((queue
->wake_bits
& QS_PAINT
) &&
832 (WM_PAINT
>= req
->get_first
) && (WM_PAINT
<= req
->get_last
))
834 req
->kind
= POST_MESSAGE
;
847 /* now check for timer */
848 if ((timer
= find_expired_timer( queue
, req
->get_win
, req
->get_first
,
849 req
->get_last
, (req
->flags
& GET_MSG_REMOVE
) )))
851 req
->kind
= POST_MESSAGE
;
853 req
->win
= timer
->win
;
854 req
->msg
= timer
->msg
;
855 req
->wparam
= timer
->id
;
856 req
->lparam
= timer
->lparam
;
865 set_error( STATUS_PENDING
); /* FIXME */
869 /* reply to a sent message */
870 DECL_HANDLER(reply_message
)
872 if (current
->queue
&& current
->queue
->recv_result
)
873 reply_message( current
->queue
, req
->result
, 0, req
->remove
);
875 set_error( STATUS_ACCESS_DENIED
);
879 /* retrieve the reply for the last message sent */
880 DECL_HANDLER(get_message_reply
)
882 if (current
->queue
) req
->result
= get_message_reply( current
->queue
, req
->cancel
);
883 else set_error( STATUS_ACCESS_DENIED
);
887 /* check if we are processing a sent message */
888 DECL_HANDLER(in_send_message
)
894 struct message_result
*result
= current
->queue
->recv_result
;
897 flags
|= ISMEX_SEND
; /* FIXME */
898 if (result
->replied
|| !result
->sender
) flags
|= ISMEX_REPLIED
;
905 /* cleanup a queue when a window is deleted */
906 DECL_HANDLER(cleanup_window_queue
)
908 if (current
->queue
) cleanup_window( current
->queue
, req
->win
);
912 /* set a window timer */
913 DECL_HANDLER(set_win_timer
)
916 struct msg_queue
*queue
= get_current_queue();
920 /* remove it if it existed already */
921 if (req
->win
) kill_timer( queue
, req
->win
, req
->msg
, req
->id
);
923 if ((timer
= set_timer( queue
, req
->rate
)))
925 timer
->win
= req
->win
;
926 timer
->msg
= req
->msg
;
928 timer
->lparam
= req
->lparam
;
932 /* kill a window timer */
933 DECL_HANDLER(kill_win_timer
)
935 struct msg_queue
*queue
= current
->queue
;
937 if (!queue
|| !kill_timer( queue
, req
->win
, req
->msg
, req
->id
))
938 set_error( STATUS_INVALID_PARAMETER
);