blob: c874f39e2d1acbbe6fd71b62e51306368b4b12d1 [file] [log] [blame]
Alexandre Julliardb817f4f1996-03-14 18:08:34 +00001/*
2 * Message queues related functions
3 *
4 * Copyright 1993, 1994 Alexandre Julliard
5 */
6
7#include <stdlib.h>
8#include "module.h"
9#include "queue.h"
10#include "win.h"
11#include "stddebug.h"
12#include "debug.h"
13
14#define MAX_QUEUE_SIZE 120 /* Max. size of a message queue */
15
16static HQUEUE hFirstQueue = 0;
17static HQUEUE hmemSysMsgQueue = 0;
18static MESSAGEQUEUE *sysMsgQueue = NULL;
19
20
21/***********************************************************************
22 * QUEUE_DumpQueue
23 */
24void QUEUE_DumpQueue( HQUEUE hQueue )
25{
26 MESSAGEQUEUE *pq;
27
Alexandre Julliard1285c2f1996-05-06 16:06:24 +000028 if (!(pq = (MESSAGEQUEUE*) GlobalLock16( hQueue )) ||
29 GlobalSize16(hQueue) < sizeof(MESSAGEQUEUE)+pq->queueSize*sizeof(QMSG))
Alexandre Julliardb817f4f1996-03-14 18:08:34 +000030 {
Alexandre Julliard59730ae1996-03-24 16:20:51 +000031 fprintf( stderr, "%04x is not a queue handle\n", hQueue );
Alexandre Julliardb817f4f1996-03-14 18:08:34 +000032 return;
33 }
34
35 fprintf( stderr,
36 "next: %12.4x Intertask SendMessage:\n"
37 "hTask: %11.4x ----------------------\n"
38 "msgSize: %9.4x hWnd: %10.4x\n"
39 "msgCount: %8.4x msg: %11.4x\n"
40 "msgNext: %9.4x wParam: %8.4x\n"
41 "msgFree: %9.4x lParam: %8.8x\n"
42 "qSize: %11.4x lRet: %10.8x\n"
43 "wWinVer: %9.4x ISMH: %10.4x\n"
44 "paints: %10.4x hSendTask: %5.4x\n"
45 "timers: %10.4x hPrevSend: %5.4x\n"
46 "wakeBits: %8.4x\n"
47 "wakeMask: %8.4x\n"
48 "hCurHook: %8.4x\n",
49 pq->next, pq->hTask, pq->msgSize, pq->hWnd,
50 pq->msgCount, pq->msg, pq->nextMessage, pq->wParam,
51 pq->nextFreeMessage, (unsigned)pq->lParam, pq->queueSize,
52 (unsigned)pq->SendMessageReturn, pq->wWinVersion, pq->InSendMessageHandle,
53 pq->wPaintCount, pq->hSendingTask, pq->wTimerCount,
54 pq->hPrevSendingTask, pq->status, pq->wakeMask, pq->hCurHook);
55}
56
57
58/***********************************************************************
59 * QUEUE_WalkQueues
60 */
61void QUEUE_WalkQueues(void)
62{
63 HQUEUE hQueue = hFirstQueue;
64
65 fprintf( stderr, "Queue Size Msgs Task\n" );
66 while (hQueue)
67 {
Alexandre Julliard1285c2f1996-05-06 16:06:24 +000068 MESSAGEQUEUE *queue = (MESSAGEQUEUE *)GlobalLock16( hQueue );
Alexandre Julliardb817f4f1996-03-14 18:08:34 +000069 if (!queue)
70 {
Alexandre Julliard59730ae1996-03-24 16:20:51 +000071 fprintf( stderr, "*** Bad queue handle %04x\n", hQueue );
Alexandre Julliardb817f4f1996-03-14 18:08:34 +000072 return;
73 }
74 fprintf( stderr, "%04x %5d %4d %04x %s\n",
75 hQueue, queue->msgSize, queue->msgCount, queue->hTask,
76 MODULE_GetModuleName( GetExePtr(queue->hTask) ) );
77 hQueue = queue->next;
78 }
79 fprintf( stderr, "\n" );
80}
81
82
83/***********************************************************************
84 * QUEUE_CreateMsgQueue
85 *
86 * Creates a message queue. Doesn't link it into queue list!
87 */
88static HQUEUE QUEUE_CreateMsgQueue( int size )
89{
90 HQUEUE hQueue;
91 MESSAGEQUEUE * msgQueue;
92 int queueSize;
93
Alexandre Julliard2ace16a1996-04-28 15:09:19 +000094 dprintf_msg(stddeb,"Creating message queue...\n");
95
Alexandre Julliardb817f4f1996-03-14 18:08:34 +000096 queueSize = sizeof(MESSAGEQUEUE) + size * sizeof(QMSG);
Alexandre Julliard1285c2f1996-05-06 16:06:24 +000097 if (!(hQueue = GlobalAlloc16( GMEM_FIXED | GMEM_ZEROINIT, queueSize )))
Alexandre Julliardb817f4f1996-03-14 18:08:34 +000098 return 0;
Alexandre Julliard1285c2f1996-05-06 16:06:24 +000099 msgQueue = (MESSAGEQUEUE *) GlobalLock16( hQueue );
Alexandre Julliardb817f4f1996-03-14 18:08:34 +0000100 msgQueue->msgSize = sizeof(QMSG);
101 msgQueue->queueSize = size;
102 msgQueue->wWinVersion = 0; /* FIXME? */
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000103 GlobalUnlock16( hQueue );
Alexandre Julliardb817f4f1996-03-14 18:08:34 +0000104 return hQueue;
105}
106
107
108/***********************************************************************
109 * QUEUE_DeleteMsgQueue
110 *
111 * Unlinks and deletes a message queue.
112 */
113BOOL QUEUE_DeleteMsgQueue( HQUEUE hQueue )
114{
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000115 MESSAGEQUEUE * msgQueue = (MESSAGEQUEUE*)GlobalLock16(hQueue);
Alexandre Julliardb817f4f1996-03-14 18:08:34 +0000116 HQUEUE *pPrev;
117
Alexandre Julliard2ace16a1996-04-28 15:09:19 +0000118 dprintf_msg(stddeb,"Deleting message queue %04x\n", hQueue);
119
Alexandre Julliardb817f4f1996-03-14 18:08:34 +0000120 if (!hQueue || !msgQueue)
121 {
122 dprintf_msg(stddeb,"DeleteMsgQueue: invalid argument.\n");
123 return 0;
124 }
125
126 pPrev = &hFirstQueue;
127 while (*pPrev && (*pPrev != hQueue))
128 {
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000129 MESSAGEQUEUE *msgQ = (MESSAGEQUEUE*)GlobalLock16(*pPrev);
Alexandre Julliardb817f4f1996-03-14 18:08:34 +0000130 pPrev = &msgQ->next;
131 }
132 if (*pPrev) *pPrev = msgQueue->next;
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000133 GlobalFree16( hQueue );
Alexandre Julliardb817f4f1996-03-14 18:08:34 +0000134 return 1;
135}
136
137
138/***********************************************************************
139 * QUEUE_CreateSysMsgQueue
140 *
141 * Create the system message queue, and set the double-click speed.
142 * Must be called only once.
143 */
144BOOL QUEUE_CreateSysMsgQueue( int size )
145{
146 if (size > MAX_QUEUE_SIZE) size = MAX_QUEUE_SIZE;
147 else if (size <= 0) size = 1;
148 if (!(hmemSysMsgQueue = QUEUE_CreateMsgQueue( size ))) return FALSE;
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000149 sysMsgQueue = (MESSAGEQUEUE *) GlobalLock16( hmemSysMsgQueue );
Alexandre Julliardb817f4f1996-03-14 18:08:34 +0000150 return TRUE;
151}
152
153
154/***********************************************************************
155 * QUEUE_GetSysQueue
156 */
157MESSAGEQUEUE *QUEUE_GetSysQueue(void)
158{
159 return sysMsgQueue;
160}
161
162
163/***********************************************************************
164 * QUEUE_AddMsg
165 *
166 * Add a message to the queue. Return FALSE if queue is full.
167 */
168BOOL QUEUE_AddMsg( HQUEUE hQueue, MSG * msg, DWORD extraInfo )
169{
170 int pos;
171 MESSAGEQUEUE *msgQueue;
172
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000173 if (!(msgQueue = (MESSAGEQUEUE *)GlobalLock16( hQueue ))) return FALSE;
Alexandre Julliardb817f4f1996-03-14 18:08:34 +0000174 pos = msgQueue->nextFreeMessage;
175
176 /* Check if queue is full */
177 if ((pos == msgQueue->nextMessage) && (msgQueue->msgCount > 0))
178 {
179 fprintf(stderr,"MSG_AddMsg // queue is full !\n");
180 return FALSE;
181 }
182
183 /* Store message */
184 msgQueue->messages[pos].msg = *msg;
185 msgQueue->messages[pos].extraInfo = extraInfo;
186 if (pos < msgQueue->queueSize-1) pos++;
187 else pos = 0;
188 msgQueue->nextFreeMessage = pos;
189 msgQueue->msgCount++;
190 msgQueue->status |= QS_POSTMESSAGE;
191 msgQueue->tempStatus |= QS_POSTMESSAGE;
192 return TRUE;
193}
194
195
196/***********************************************************************
197 * QUEUE_FindMsg
198 *
199 * Find a message matching the given parameters. Return -1 if none available.
200 */
201int QUEUE_FindMsg( MESSAGEQUEUE * msgQueue, HWND hwnd, int first, int last )
202{
203 int i, pos = msgQueue->nextMessage;
204
Alexandre Julliard59730ae1996-03-24 16:20:51 +0000205 dprintf_msg(stddeb,"MSG_FindMsg: hwnd=%04x\n\n", hwnd );
Alexandre Julliardb817f4f1996-03-14 18:08:34 +0000206
207 if (!msgQueue->msgCount) return -1;
208 if (!hwnd && !first && !last) return pos;
209
210 for (i = 0; i < msgQueue->msgCount; i++)
211 {
212 MSG * msg = &msgQueue->messages[pos].msg;
213
214 if (!hwnd || (msg->hwnd == hwnd))
215 {
216 if (!first && !last) return pos;
217 if ((msg->message >= first) && (msg->message <= last)) return pos;
218 }
219 if (pos < msgQueue->queueSize-1) pos++;
220 else pos = 0;
221 }
222 return -1;
223}
224
225
226/***********************************************************************
227 * QUEUE_RemoveMsg
228 *
229 * Remove a message from the queue (pos must be a valid position).
230 */
231void QUEUE_RemoveMsg( MESSAGEQUEUE * msgQueue, int pos )
232{
233 if (pos >= msgQueue->nextMessage)
234 {
235 for ( ; pos > msgQueue->nextMessage; pos--)
236 msgQueue->messages[pos] = msgQueue->messages[pos-1];
237 msgQueue->nextMessage++;
238 if (msgQueue->nextMessage >= msgQueue->queueSize)
239 msgQueue->nextMessage = 0;
240 }
241 else
242 {
243 for ( ; pos < msgQueue->nextFreeMessage; pos++)
244 msgQueue->messages[pos] = msgQueue->messages[pos+1];
245 if (msgQueue->nextFreeMessage) msgQueue->nextFreeMessage--;
246 else msgQueue->nextFreeMessage = msgQueue->queueSize-1;
247 }
248 msgQueue->msgCount--;
249 if (!msgQueue->msgCount) msgQueue->status &= ~QS_POSTMESSAGE;
250 msgQueue->tempStatus = 0;
251}
252
253
254/***********************************************************************
255 * hardware_event
256 *
257 * Add an event to the system message queue.
258 * Note: the position is relative to the desktop window.
259 */
260void hardware_event( WORD message, WORD wParam, LONG lParam,
261 int xPos, int yPos, DWORD time, DWORD extraInfo )
262{
263 MSG *msg;
264 int pos;
265
266 if (!sysMsgQueue) return;
267 pos = sysMsgQueue->nextFreeMessage;
268
269 /* Merge with previous event if possible */
270
271 if ((message == WM_MOUSEMOVE) && sysMsgQueue->msgCount)
272 {
273 if (pos > 0) pos--;
274 else pos = sysMsgQueue->queueSize - 1;
275 msg = &sysMsgQueue->messages[pos].msg;
276 if ((msg->message == message) && (msg->wParam == wParam))
277 sysMsgQueue->msgCount--; /* Merge events */
278 else
279 pos = sysMsgQueue->nextFreeMessage; /* Don't merge */
280 }
281
282 /* Check if queue is full */
283
284 if ((pos == sysMsgQueue->nextMessage) && sysMsgQueue->msgCount)
285 {
286 /* Queue is full, beep (but not on every mouse motion...) */
287 if (message != WM_MOUSEMOVE) MessageBeep(0);
288 return;
289 }
290
291 /* Store message */
292
293 msg = &sysMsgQueue->messages[pos].msg;
294 msg->hwnd = 0;
295 msg->message = message;
296 msg->wParam = wParam;
297 msg->lParam = lParam;
298 msg->time = time;
299 msg->pt.x = xPos & 0xffff;
300 msg->pt.y = yPos & 0xffff;
301 sysMsgQueue->messages[pos].extraInfo = extraInfo;
302 if (pos < sysMsgQueue->queueSize - 1) pos++;
303 else pos = 0;
304 sysMsgQueue->nextFreeMessage = pos;
305 sysMsgQueue->msgCount++;
306}
307
308
309/***********************************************************************
310 * QUEUE_GetQueueTask
311 */
312HTASK QUEUE_GetQueueTask( HQUEUE hQueue )
313{
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000314 MESSAGEQUEUE *queue = GlobalLock16( hQueue );
Alexandre Julliardb817f4f1996-03-14 18:08:34 +0000315 return (queue) ? queue->hTask : 0 ;
316}
317
318
319/***********************************************************************
320 * QUEUE_IncPaintCount
321 */
322void QUEUE_IncPaintCount( HQUEUE hQueue )
323{
324 MESSAGEQUEUE *queue;
325
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000326 if (!(queue = (MESSAGEQUEUE *)GlobalLock16( hQueue ))) return;
Alexandre Julliardb817f4f1996-03-14 18:08:34 +0000327 queue->wPaintCount++;
328 queue->status |= QS_PAINT;
329 queue->tempStatus |= QS_PAINT;
330}
331
332
333/***********************************************************************
334 * QUEUE_DecPaintCount
335 */
336void QUEUE_DecPaintCount( HQUEUE hQueue )
337{
338 MESSAGEQUEUE *queue;
339
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000340 if (!(queue = (MESSAGEQUEUE *)GlobalLock16( hQueue ))) return;
Alexandre Julliardb817f4f1996-03-14 18:08:34 +0000341 queue->wPaintCount--;
342 if (!queue->wPaintCount) queue->status &= ~QS_PAINT;
343}
344
345
346/***********************************************************************
347 * QUEUE_IncTimerCount
348 */
349void QUEUE_IncTimerCount( HQUEUE hQueue )
350{
351 MESSAGEQUEUE *queue;
352
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000353 if (!(queue = (MESSAGEQUEUE *)GlobalLock16( hQueue ))) return;
Alexandre Julliardb817f4f1996-03-14 18:08:34 +0000354 queue->wTimerCount++;
355 queue->status |= QS_TIMER;
356 queue->tempStatus |= QS_TIMER;
357}
358
359
360/***********************************************************************
361 * QUEUE_DecTimerCount
362 */
363void QUEUE_DecTimerCount( HQUEUE hQueue )
364{
365 MESSAGEQUEUE *queue;
366
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000367 if (!(queue = (MESSAGEQUEUE *)GlobalLock16( hQueue ))) return;
Alexandre Julliardb817f4f1996-03-14 18:08:34 +0000368 queue->wTimerCount--;
369 if (!queue->wTimerCount) queue->status &= ~QS_TIMER;
370}
371
372
373/***********************************************************************
374 * PostQuitMessage (USER.6)
375 */
376void PostQuitMessage( INT exitCode )
377{
378 MESSAGEQUEUE *queue;
379
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000380 if (!(queue = (MESSAGEQUEUE *)GlobalLock16( GetTaskQueue(0) ))) return;
Alexandre Julliardb817f4f1996-03-14 18:08:34 +0000381 queue->wPostQMsg = TRUE;
382 queue->wExitCode = (WORD)exitCode;
383}
384
385
386/***********************************************************************
387 * GetWindowTask (USER.224)
388 */
389HTASK GetWindowTask( HWND hwnd )
390{
391 WND *wndPtr = WIN_FindWndPtr( hwnd );
392
393 if (!wndPtr) return 0;
394 return QUEUE_GetQueueTask( wndPtr->hmemTaskQ );
395}
396
397
398/***********************************************************************
399 * SetMessageQueue (USER.266)
400 */
401BOOL SetMessageQueue( int size )
402{
403 HQUEUE hQueue, hNewQueue;
404 MESSAGEQUEUE *queuePtr;
405
Alexandre Julliard2ace16a1996-04-28 15:09:19 +0000406 dprintf_msg(stddeb,"SetMessageQueue: task %04x size %i\n", GetCurrentTask(), size);
407
Alexandre Julliardb817f4f1996-03-14 18:08:34 +0000408 if ((size > MAX_QUEUE_SIZE) || (size <= 0)) return TRUE;
409
410 if( !(hNewQueue = QUEUE_CreateMsgQueue( size )))
411 {
412 dprintf_msg(stddeb,"SetMessageQueue: failed!\n");
413 return FALSE;
414 }
415
416 /* Free the old message queue */
417 if ((hQueue = GetTaskQueue(0)) != 0) QUEUE_DeleteMsgQueue( hQueue );
418
419 /* Link new queue into list */
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000420 queuePtr = (MESSAGEQUEUE *)GlobalLock16( hNewQueue );
Alexandre Julliardb817f4f1996-03-14 18:08:34 +0000421 queuePtr->hTask = GetCurrentTask();
422 queuePtr->next = hFirstQueue;
423 hFirstQueue = hNewQueue;
424
425 SetTaskQueue( 0, hNewQueue );
426 return TRUE;
427}
428
429
430/***********************************************************************
431 * GetQueueStatus (USER.334)
432 */
433DWORD GetQueueStatus( UINT flags )
434{
435 MESSAGEQUEUE *queue;
436 DWORD ret;
437
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000438 if (!(queue = (MESSAGEQUEUE *)GlobalLock16( GetTaskQueue(0) ))) return 0;
Alexandre Julliardb817f4f1996-03-14 18:08:34 +0000439 ret = MAKELONG( queue->tempStatus, queue->status );
440 queue->tempStatus = 0;
441 return ret & MAKELONG( flags, flags );
442}
443
444
445/***********************************************************************
446 * GetInputState (USER.335)
447 */
448BOOL GetInputState()
449{
450 MESSAGEQUEUE *queue;
451
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000452 if (!(queue = (MESSAGEQUEUE *)GlobalLock16( GetTaskQueue(0) ))) return FALSE;
Alexandre Julliardb817f4f1996-03-14 18:08:34 +0000453 return queue->status & (QS_KEY | QS_MOUSEBUTTON);
454}
455
456
457/***********************************************************************
458 * GetMessagePos (USER.119)
459 */
460DWORD GetMessagePos(void)
461{
462 MESSAGEQUEUE *queue;
463
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000464 if (!(queue = (MESSAGEQUEUE *)GlobalLock16( GetTaskQueue(0) ))) return 0;
Alexandre Julliardb817f4f1996-03-14 18:08:34 +0000465 return queue->GetMessagePosVal;
466}
467
468
469/***********************************************************************
470 * GetMessageTime (USER.120)
471 */
472LONG GetMessageTime(void)
473{
474 MESSAGEQUEUE *queue;
475
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000476 if (!(queue = (MESSAGEQUEUE *)GlobalLock16( GetTaskQueue(0) ))) return 0;
Alexandre Julliardb817f4f1996-03-14 18:08:34 +0000477 return queue->GetMessageTimeVal;
478}
479
480
481/***********************************************************************
482 * GetMessageExtraInfo (USER.288)
483 */
484LONG GetMessageExtraInfo(void)
485{
486 MESSAGEQUEUE *queue;
487
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000488 if (!(queue = (MESSAGEQUEUE *)GlobalLock16( GetTaskQueue(0) ))) return 0;
Alexandre Julliardb817f4f1996-03-14 18:08:34 +0000489 return queue->GetMessageExtraInfoVal;
490}