2 * Message queues related functions
4 * Copyright 1993, 1994 Alexandre Julliard
14 #define MAX_QUEUE_SIZE 120 /* Max. size of a message queue */
16 static HQUEUE hFirstQueue
= 0;
17 static HQUEUE hmemSysMsgQueue
= 0;
18 static HQUEUE hDoomedQueue
= 0;
19 static MESSAGEQUEUE
*sysMsgQueue
= NULL
;
21 /***********************************************************************
22 * QUEUE_GetDoomedQueue/QUEUE_SetDoomedQueue
24 HQUEUE
QUEUE_GetDoomedQueue()
28 void QUEUE_SetDoomedQueue(HQUEUE hQueue
)
30 hDoomedQueue
= hQueue
;
33 /***********************************************************************
36 void QUEUE_DumpQueue( HQUEUE hQueue
)
40 if (!(pq
= (MESSAGEQUEUE
*) GlobalLock16( hQueue
)) ||
41 GlobalSize16(hQueue
) < sizeof(MESSAGEQUEUE
)+pq
->queueSize
*sizeof(QMSG
))
43 fprintf( stderr
, "%04x is not a queue handle\n", hQueue
);
48 "next: %12.4x Intertask SendMessage:\n"
49 "hTask: %11.4x ----------------------\n"
50 "msgSize: %9.4x hWnd: %10.4x\n"
51 "msgCount: %8.4x msg: %11.4x\n"
52 "msgNext: %9.4x wParam: %8.4x\n"
53 "msgFree: %9.4x lParam: %8.8x\n"
54 "qSize: %11.4x lRet: %10.8x\n"
55 "wWinVer: %9.4x ISMH: %10.4x\n"
56 "paints: %10.4x hSendTask: %5.4x\n"
57 "timers: %10.4x hPrevSend: %5.4x\n"
61 pq
->next
, pq
->hTask
, pq
->msgSize
, pq
->hWnd
,
62 pq
->msgCount
, pq
->msg
, pq
->nextMessage
, pq
->wParam
,
63 pq
->nextFreeMessage
, (unsigned)pq
->lParam
, pq
->queueSize
,
64 (unsigned)pq
->SendMessageReturn
, pq
->wWinVersion
, pq
->InSendMessageHandle
,
65 pq
->wPaintCount
, pq
->hSendingTask
, pq
->wTimerCount
,
66 pq
->hPrevSendingTask
, pq
->status
, pq
->wakeMask
, pq
->hCurHook
);
70 /***********************************************************************
73 void QUEUE_WalkQueues(void)
75 HQUEUE hQueue
= hFirstQueue
;
77 fprintf( stderr
, "Queue Size Msgs Task\n" );
80 MESSAGEQUEUE
*queue
= (MESSAGEQUEUE
*)GlobalLock16( hQueue
);
83 fprintf( stderr
, "*** Bad queue handle %04x\n", hQueue
);
86 fprintf( stderr
, "%04x %5d %4d %04x %s\n",
87 hQueue
, queue
->msgSize
, queue
->msgCount
, queue
->hTask
,
88 MODULE_GetModuleName( GetExePtr(queue
->hTask
) ) );
91 fprintf( stderr
, "\n" );
95 /***********************************************************************
96 * QUEUE_CreateMsgQueue
98 * Creates a message queue. Doesn't link it into queue list!
100 static HQUEUE
QUEUE_CreateMsgQueue( int size
)
103 MESSAGEQUEUE
* msgQueue
;
106 dprintf_msg(stddeb
,"Creating message queue...\n");
108 queueSize
= sizeof(MESSAGEQUEUE
) + size
* sizeof(QMSG
);
109 if (!(hQueue
= GlobalAlloc16( GMEM_FIXED
| GMEM_ZEROINIT
, queueSize
)))
111 msgQueue
= (MESSAGEQUEUE
*) GlobalLock16( hQueue
);
112 msgQueue
->msgSize
= sizeof(QMSG
);
113 msgQueue
->queueSize
= size
;
114 msgQueue
->wWinVersion
= 0; /* FIXME? */
115 GlobalUnlock16( hQueue
);
120 /***********************************************************************
121 * QUEUE_DeleteMsgQueue
123 * Unlinks and deletes a message queue.
125 BOOL
QUEUE_DeleteMsgQueue( HQUEUE hQueue
)
127 MESSAGEQUEUE
* msgQueue
= (MESSAGEQUEUE
*)GlobalLock16(hQueue
);
130 dprintf_msg(stddeb
,"Deleting message queue %04x\n", hQueue
);
132 if (!hQueue
|| !msgQueue
)
134 dprintf_msg(stddeb
,"DeleteMsgQueue: invalid argument.\n");
138 pPrev
= &hFirstQueue
;
139 while (*pPrev
&& (*pPrev
!= hQueue
))
141 MESSAGEQUEUE
*msgQ
= (MESSAGEQUEUE
*)GlobalLock16(*pPrev
);
144 if (*pPrev
) *pPrev
= msgQueue
->next
;
145 GlobalFree16( hQueue
);
150 /***********************************************************************
151 * QUEUE_CreateSysMsgQueue
153 * Create the system message queue, and set the double-click speed.
154 * Must be called only once.
156 BOOL
QUEUE_CreateSysMsgQueue( int size
)
158 if (size
> MAX_QUEUE_SIZE
) size
= MAX_QUEUE_SIZE
;
159 else if (size
<= 0) size
= 1;
160 if (!(hmemSysMsgQueue
= QUEUE_CreateMsgQueue( size
))) return FALSE
;
161 sysMsgQueue
= (MESSAGEQUEUE
*) GlobalLock16( hmemSysMsgQueue
);
166 /***********************************************************************
169 MESSAGEQUEUE
*QUEUE_GetSysQueue(void)
175 /***********************************************************************
178 * Add a message to the queue. Return FALSE if queue is full.
180 BOOL
QUEUE_AddMsg( HQUEUE hQueue
, MSG
* msg
, DWORD extraInfo
)
183 MESSAGEQUEUE
*msgQueue
;
185 if (!(msgQueue
= (MESSAGEQUEUE
*)GlobalLock16( hQueue
))) return FALSE
;
186 pos
= msgQueue
->nextFreeMessage
;
188 /* Check if queue is full */
189 if ((pos
== msgQueue
->nextMessage
) && (msgQueue
->msgCount
> 0))
191 fprintf(stderr
,"MSG_AddMsg // queue is full !\n");
196 msgQueue
->messages
[pos
].msg
= *msg
;
197 msgQueue
->messages
[pos
].extraInfo
= extraInfo
;
198 if (pos
< msgQueue
->queueSize
-1) pos
++;
200 msgQueue
->nextFreeMessage
= pos
;
201 msgQueue
->msgCount
++;
202 msgQueue
->status
|= QS_POSTMESSAGE
;
203 msgQueue
->tempStatus
|= QS_POSTMESSAGE
;
208 /***********************************************************************
211 * Find a message matching the given parameters. Return -1 if none available.
213 int QUEUE_FindMsg( MESSAGEQUEUE
* msgQueue
, HWND hwnd
, int first
, int last
)
215 int i
, pos
= msgQueue
->nextMessage
;
217 dprintf_msg(stddeb
,"QUEUE_FindMsg: hwnd=%04x pos=%d\n", hwnd
, pos
);
219 if (!msgQueue
->msgCount
) return -1;
220 if (!hwnd
&& !first
&& !last
) return pos
;
222 for (i
= 0; i
< msgQueue
->msgCount
; i
++)
224 MSG
* msg
= &msgQueue
->messages
[pos
].msg
;
226 if (!hwnd
|| (msg
->hwnd
== hwnd
))
228 if (!first
&& !last
) return pos
;
229 if ((msg
->message
>= first
) && (msg
->message
<= last
)) return pos
;
231 if (pos
< msgQueue
->queueSize
-1) pos
++;
238 /***********************************************************************
241 * Remove a message from the queue (pos must be a valid position).
243 void QUEUE_RemoveMsg( MESSAGEQUEUE
* msgQueue
, int pos
)
245 if (pos
>= msgQueue
->nextMessage
)
247 for ( ; pos
> msgQueue
->nextMessage
; pos
--)
248 msgQueue
->messages
[pos
] = msgQueue
->messages
[pos
-1];
249 msgQueue
->nextMessage
++;
250 if (msgQueue
->nextMessage
>= msgQueue
->queueSize
)
251 msgQueue
->nextMessage
= 0;
255 for ( ; pos
< msgQueue
->nextFreeMessage
; pos
++)
256 msgQueue
->messages
[pos
] = msgQueue
->messages
[pos
+1];
257 if (msgQueue
->nextFreeMessage
) msgQueue
->nextFreeMessage
--;
258 else msgQueue
->nextFreeMessage
= msgQueue
->queueSize
-1;
260 msgQueue
->msgCount
--;
261 if (!msgQueue
->msgCount
) msgQueue
->status
&= ~QS_POSTMESSAGE
;
262 msgQueue
->tempStatus
= 0;
266 /***********************************************************************
269 * Add an event to the system message queue.
270 * Note: the position is relative to the desktop window.
272 void hardware_event( WORD message
, WORD wParam
, LONG lParam
,
273 int xPos
, int yPos
, DWORD time
, DWORD extraInfo
)
278 if (!sysMsgQueue
) return;
279 pos
= sysMsgQueue
->nextFreeMessage
;
281 /* Merge with previous event if possible */
283 if ((message
== WM_MOUSEMOVE
) && sysMsgQueue
->msgCount
)
286 else pos
= sysMsgQueue
->queueSize
- 1;
287 msg
= &sysMsgQueue
->messages
[pos
].msg
;
288 if ((msg
->message
== message
) && (msg
->wParam
== wParam
))
289 sysMsgQueue
->msgCount
--; /* Merge events */
291 pos
= sysMsgQueue
->nextFreeMessage
; /* Don't merge */
294 /* Check if queue is full */
296 if ((pos
== sysMsgQueue
->nextMessage
) && sysMsgQueue
->msgCount
)
298 /* Queue is full, beep (but not on every mouse motion...) */
299 if (message
!= WM_MOUSEMOVE
) MessageBeep(0);
305 msg
= &sysMsgQueue
->messages
[pos
].msg
;
307 msg
->message
= message
;
308 msg
->wParam
= wParam
;
309 msg
->lParam
= lParam
;
311 msg
->pt
.x
= xPos
& 0xffff;
312 msg
->pt
.y
= yPos
& 0xffff;
313 sysMsgQueue
->messages
[pos
].extraInfo
= extraInfo
;
314 if (pos
< sysMsgQueue
->queueSize
- 1) pos
++;
316 sysMsgQueue
->nextFreeMessage
= pos
;
317 sysMsgQueue
->msgCount
++;
321 /***********************************************************************
324 HTASK
QUEUE_GetQueueTask( HQUEUE hQueue
)
326 MESSAGEQUEUE
*queue
= GlobalLock16( hQueue
);
327 return (queue
) ? queue
->hTask
: 0 ;
331 /***********************************************************************
332 * QUEUE_IncPaintCount
334 void QUEUE_IncPaintCount( HQUEUE hQueue
)
338 if (!(queue
= (MESSAGEQUEUE
*)GlobalLock16( hQueue
))) return;
339 queue
->wPaintCount
++;
340 queue
->status
|= QS_PAINT
;
341 queue
->tempStatus
|= QS_PAINT
;
345 /***********************************************************************
346 * QUEUE_DecPaintCount
348 void QUEUE_DecPaintCount( HQUEUE hQueue
)
352 if (!(queue
= (MESSAGEQUEUE
*)GlobalLock16( hQueue
))) return;
353 queue
->wPaintCount
--;
354 if (!queue
->wPaintCount
) queue
->status
&= ~QS_PAINT
;
358 /***********************************************************************
359 * QUEUE_IncTimerCount
361 void QUEUE_IncTimerCount( HQUEUE hQueue
)
365 if (!(queue
= (MESSAGEQUEUE
*)GlobalLock16( hQueue
))) return;
366 queue
->wTimerCount
++;
367 queue
->status
|= QS_TIMER
;
368 queue
->tempStatus
|= QS_TIMER
;
372 /***********************************************************************
373 * QUEUE_DecTimerCount
375 void QUEUE_DecTimerCount( HQUEUE hQueue
)
379 if (!(queue
= (MESSAGEQUEUE
*)GlobalLock16( hQueue
))) return;
380 queue
->wTimerCount
--;
381 if (!queue
->wTimerCount
) queue
->status
&= ~QS_TIMER
;
385 /***********************************************************************
386 * PostQuitMessage (USER.6)
388 void PostQuitMessage( INT exitCode
)
392 if (!(queue
= (MESSAGEQUEUE
*)GlobalLock16( GetTaskQueue(0) ))) return;
393 queue
->wPostQMsg
= TRUE
;
394 queue
->wExitCode
= (WORD
)exitCode
;
398 /***********************************************************************
399 * GetWindowTask (USER.224)
401 HTASK
GetWindowTask( HWND hwnd
)
403 WND
*wndPtr
= WIN_FindWndPtr( hwnd
);
405 if (!wndPtr
) return 0;
406 return QUEUE_GetQueueTask( wndPtr
->hmemTaskQ
);
410 /***********************************************************************
411 * SetMessageQueue (USER.266)
413 BOOL
SetMessageQueue( int size
)
415 HQUEUE hQueue
, hNewQueue
;
416 MESSAGEQUEUE
*queuePtr
;
418 dprintf_msg(stddeb
,"SetMessageQueue: task %04x size %i\n", GetCurrentTask(), size
);
420 if ((size
> MAX_QUEUE_SIZE
) || (size
<= 0)) return TRUE
;
422 if( !(hNewQueue
= QUEUE_CreateMsgQueue( size
)))
424 dprintf_msg(stddeb
,"SetMessageQueue: failed!\n");
428 /* Free the old message queue */
429 if ((hQueue
= GetTaskQueue(0)) != 0) QUEUE_DeleteMsgQueue( hQueue
);
431 /* Link new queue into list */
432 queuePtr
= (MESSAGEQUEUE
*)GlobalLock16( hNewQueue
);
433 queuePtr
->hTask
= GetCurrentTask();
434 queuePtr
->next
= hFirstQueue
;
435 hFirstQueue
= hNewQueue
;
437 SetTaskQueue( 0, hNewQueue
);
442 /***********************************************************************
443 * GetQueueStatus (USER.334)
445 DWORD
GetQueueStatus( UINT flags
)
450 if (!(queue
= (MESSAGEQUEUE
*)GlobalLock16( GetTaskQueue(0) ))) return 0;
451 ret
= MAKELONG( queue
->tempStatus
, queue
->status
);
452 queue
->tempStatus
= 0;
453 return ret
& MAKELONG( flags
, flags
);
457 /***********************************************************************
458 * GetInputState (USER.335)
464 if (!(queue
= (MESSAGEQUEUE
*)GlobalLock16( GetTaskQueue(0) ))) return FALSE
;
465 return queue
->status
& (QS_KEY
| QS_MOUSEBUTTON
);
469 /***********************************************************************
470 * GetMessagePos (USER.119)
472 DWORD
GetMessagePos(void)
476 if (!(queue
= (MESSAGEQUEUE
*)GlobalLock16( GetTaskQueue(0) ))) return 0;
477 return queue
->GetMessagePosVal
;
481 /***********************************************************************
482 * GetMessageTime (USER.120)
484 LONG
GetMessageTime(void)
488 if (!(queue
= (MESSAGEQUEUE
*)GlobalLock16( GetTaskQueue(0) ))) return 0;
489 return queue
->GetMessageTimeVal
;
493 /***********************************************************************
494 * GetMessageExtraInfo (USER.288)
496 LONG
GetMessageExtraInfo(void)
500 if (!(queue
= (MESSAGEQUEUE
*)GlobalLock16( GetTaskQueue(0) ))) return 0;
501 return queue
->GetMessageExtraInfoVal
;