blob: 4d8a1604d4090349517a53e60e04cdc1bf5d216a [file] [log] [blame]
Noel Borthwickb4278561999-02-05 10:37:53 +00001/* * Message queues related functions
Alexandre Julliardb817f4f1996-03-14 18:08:34 +00002 *
3 * Copyright 1993, 1994 Alexandre Julliard
4 */
5
Alexandre Julliard8feb3bc1999-02-28 12:25:03 +00006#include <string.h>
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00007#include <signal.h>
Marcus Meissner317af321999-02-17 13:51:06 +00008#include "wine/winbase16.h"
9#include "wine/winuser16.h"
Alexandre Julliard641ee761997-08-04 16:34:36 +000010#include "miscemu.h"
Alexandre Julliardb817f4f1996-03-14 18:08:34 +000011#include "module.h"
12#include "queue.h"
Alexandre Julliardef702d81996-05-28 18:54:58 +000013#include "task.h"
Alexandre Julliardb817f4f1996-03-14 18:08:34 +000014#include "win.h"
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +000015#include "clipboard.h"
Alexandre Julliardda0cfb31996-12-01 17:17:47 +000016#include "hook.h"
Alexandre Julliard767e6f61998-08-09 12:47:43 +000017#include "heap.h"
Alexandre Julliard349a9531997-02-02 19:01:52 +000018#include "thread.h"
19#include "process.h"
Noel Borthwickb4278561999-02-05 10:37:53 +000020#include <assert.h>
Alexandre Julliardb817f4f1996-03-14 18:08:34 +000021#include "debug.h"
Stephane Lussier2c86dab1999-02-18 17:34:09 +000022#include "spy.h"
Alexandre Julliardb817f4f1996-03-14 18:08:34 +000023
24#define MAX_QUEUE_SIZE 120 /* Max. size of a message queue */
25
Alexandre Julliard18f92e71996-07-17 20:02:21 +000026static HQUEUE16 hFirstQueue = 0;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +000027static HQUEUE16 hExitingQueue = 0;
Alexandre Julliard18f92e71996-07-17 20:02:21 +000028static HQUEUE16 hmemSysMsgQueue = 0;
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +000029static MESSAGEQUEUE *sysMsgQueue = NULL;
Noel Borthwickb4278561999-02-05 10:37:53 +000030static PERQUEUEDATA *pQDataWin16 = NULL; /* Global perQData for Win16 tasks */
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +000031
Alexandre Julliard8b915631996-06-16 16:16:05 +000032static MESSAGEQUEUE *pMouseQueue = NULL; /* Queue for last mouse message */
33static MESSAGEQUEUE *pKbdQueue = NULL; /* Queue for last kbd message */
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +000034
Stephane Lussier1c4786f1999-01-28 10:54:11 +000035HQUEUE16 hCursorQueue = 0;
36HQUEUE16 hActiveQueue = 0;
37
38
39/***********************************************************************
Noel Borthwickb4278561999-02-05 10:37:53 +000040 * PERQDATA_CreateInstance
41 *
42 * Creates an instance of a reference counted PERQUEUEDATA element
43 * for the message queue. perQData is stored globally for 16 bit tasks.
44 *
45 * Note: We don't implement perQdata exactly the same way Windows does.
46 * Each perQData element is reference counted since it may be potentially
47 * shared by multiple message Queues (via AttachThreadInput).
48 * We only store the current values for Active, Capture and focus windows
49 * currently.
50 */
51PERQUEUEDATA * PERQDATA_CreateInstance( )
52{
53 PERQUEUEDATA *pQData;
54
55 BOOL16 bIsWin16 = 0;
56
57 TRACE(msg,"()\n");
58
59 /* Share a single instance of perQData for all 16 bit tasks */
60 if ( ( bIsWin16 = THREAD_IsWin16( THREAD_Current() ) ) )
61 {
62 /* If previously allocated, just bump up ref count */
63 if ( pQDataWin16 )
64 {
65 PERQDATA_Addref( pQDataWin16 );
66 return pQDataWin16;
67 }
68 }
69
70 /* Allocate PERQUEUEDATA from the system heap */
71 if (!( pQData = (PERQUEUEDATA *) HeapAlloc( SystemHeap, 0,
72 sizeof(PERQUEUEDATA) ) ))
73 return 0;
74
75 /* Initialize */
76 pQData->hWndCapture = pQData->hWndFocus = pQData->hWndActive = 0;
77 pQData->ulRefCount = 1;
78 pQData->nCaptureHT = HTCLIENT;
79
80 /* Note: We have an independent critical section for the per queue data
81 * since this may be shared by different threads. see AttachThreadInput()
82 */
83 InitializeCriticalSection( &pQData->cSection );
84
85 /* Save perQData globally for 16 bit tasks */
86 if ( bIsWin16 )
87 pQDataWin16 = pQData;
88
89 return pQData;
90}
91
92
93/***********************************************************************
94 * PERQDATA_Addref
95 *
96 * Increment reference count for the PERQUEUEDATA instance
97 * Returns reference count for debugging purposes
98 */
99ULONG PERQDATA_Addref( PERQUEUEDATA *pQData )
100{
101 assert(pQData != 0 );
102 TRACE(msg,"(): current refcount %lu ...\n", pQData->ulRefCount);
103
104 EnterCriticalSection( &pQData->cSection );
105 ++pQData->ulRefCount;
106 LeaveCriticalSection( &pQData->cSection );
107
108 return pQData->ulRefCount;
109}
110
111
112/***********************************************************************
113 * PERQDATA_Release
114 *
115 * Release a reference to a PERQUEUEDATA instance.
116 * Destroy the instance if no more references exist
117 * Returns reference count for debugging purposes
118 */
119ULONG PERQDATA_Release( PERQUEUEDATA *pQData )
120{
121 assert(pQData != 0 );
122 TRACE(msg,"(): current refcount %lu ...\n",
123 (LONG)pQData->ulRefCount );
124
125 EnterCriticalSection( &pQData->cSection );
126 if ( --pQData->ulRefCount == 0 )
127 {
128 LeaveCriticalSection( &pQData->cSection );
129 DeleteCriticalSection( &pQData->cSection );
130
131 TRACE(msg,"(): deleting PERQUEUEDATA instance ...\n" );
132
133 /* Deleting our global 16 bit perQData? */
134 if ( pQData == pQDataWin16 )
135 pQDataWin16 = 0;
136
137 /* Free the PERQUEUEDATA instance */
138 HeapFree( SystemHeap, 0, pQData );
139
140 return 0;
141 }
142 LeaveCriticalSection( &pQData->cSection );
143
144 return pQData->ulRefCount;
145}
146
147
148/***********************************************************************
149 * PERQDATA_GetFocusWnd
150 *
151 * Get the focus hwnd member in a threadsafe manner
152 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000153HWND PERQDATA_GetFocusWnd( PERQUEUEDATA *pQData )
Noel Borthwickb4278561999-02-05 10:37:53 +0000154{
Alexandre Julliarda3960291999-02-26 11:11:13 +0000155 HWND hWndFocus;
Noel Borthwickb4278561999-02-05 10:37:53 +0000156 assert(pQData != 0 );
157
158 EnterCriticalSection( &pQData->cSection );
159 hWndFocus = pQData->hWndFocus;
160 LeaveCriticalSection( &pQData->cSection );
161
162 return hWndFocus;
163}
164
165
166/***********************************************************************
167 * PERQDATA_SetFocusWnd
168 *
169 * Set the focus hwnd member in a threadsafe manner
170 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000171HWND PERQDATA_SetFocusWnd( PERQUEUEDATA *pQData, HWND hWndFocus )
Noel Borthwickb4278561999-02-05 10:37:53 +0000172{
Alexandre Julliarda3960291999-02-26 11:11:13 +0000173 HWND hWndFocusPrv;
Noel Borthwickb4278561999-02-05 10:37:53 +0000174 assert(pQData != 0 );
175
176 EnterCriticalSection( &pQData->cSection );
177 hWndFocusPrv = pQData->hWndFocus;
178 pQData->hWndFocus = hWndFocus;
179 LeaveCriticalSection( &pQData->cSection );
180
181 return hWndFocusPrv;
182}
183
184
185/***********************************************************************
186 * PERQDATA_GetActiveWnd
187 *
188 * Get the active hwnd member in a threadsafe manner
189 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000190HWND PERQDATA_GetActiveWnd( PERQUEUEDATA *pQData )
Noel Borthwickb4278561999-02-05 10:37:53 +0000191{
Alexandre Julliarda3960291999-02-26 11:11:13 +0000192 HWND hWndActive;
Noel Borthwickb4278561999-02-05 10:37:53 +0000193 assert(pQData != 0 );
194
195 EnterCriticalSection( &pQData->cSection );
196 hWndActive = pQData->hWndActive;
197 LeaveCriticalSection( &pQData->cSection );
198
199 return hWndActive;
200}
201
202
203/***********************************************************************
204 * PERQDATA_SetActiveWnd
205 *
206 * Set the active focus hwnd member in a threadsafe manner
207 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000208HWND PERQDATA_SetActiveWnd( PERQUEUEDATA *pQData, HWND hWndActive )
Noel Borthwickb4278561999-02-05 10:37:53 +0000209{
Alexandre Julliarda3960291999-02-26 11:11:13 +0000210 HWND hWndActivePrv;
Noel Borthwickb4278561999-02-05 10:37:53 +0000211 assert(pQData != 0 );
212
213 EnterCriticalSection( &pQData->cSection );
214 hWndActivePrv = pQData->hWndActive;
215 pQData->hWndActive = hWndActive;
216 LeaveCriticalSection( &pQData->cSection );
217
218 return hWndActivePrv;
219}
220
221
222/***********************************************************************
223 * PERQDATA_GetCaptureWnd
224 *
225 * Get the capture hwnd member in a threadsafe manner
226 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000227HWND PERQDATA_GetCaptureWnd( PERQUEUEDATA *pQData )
Noel Borthwickb4278561999-02-05 10:37:53 +0000228{
Alexandre Julliarda3960291999-02-26 11:11:13 +0000229 HWND hWndCapture;
Noel Borthwickb4278561999-02-05 10:37:53 +0000230 assert(pQData != 0 );
231
232 EnterCriticalSection( &pQData->cSection );
233 hWndCapture = pQData->hWndCapture;
234 LeaveCriticalSection( &pQData->cSection );
235
236 return hWndCapture;
237}
238
239
240/***********************************************************************
241 * PERQDATA_SetCaptureWnd
242 *
243 * Set the capture hwnd member in a threadsafe manner
244 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000245HWND PERQDATA_SetCaptureWnd( PERQUEUEDATA *pQData, HWND hWndCapture )
Noel Borthwickb4278561999-02-05 10:37:53 +0000246{
Alexandre Julliarda3960291999-02-26 11:11:13 +0000247 HWND hWndCapturePrv;
Noel Borthwickb4278561999-02-05 10:37:53 +0000248 assert(pQData != 0 );
249
250 EnterCriticalSection( &pQData->cSection );
251 hWndCapturePrv = pQData->hWndCapture;
252 pQData->hWndCapture = hWndCapture;
253 LeaveCriticalSection( &pQData->cSection );
254
255 return hWndCapturePrv;
256}
257
258
259/***********************************************************************
260 * PERQDATA_GetCaptureInfo
261 *
262 * Get the capture info member in a threadsafe manner
263 */
264INT16 PERQDATA_GetCaptureInfo( PERQUEUEDATA *pQData )
265{
266 INT16 nCaptureHT;
267 assert(pQData != 0 );
268
269 EnterCriticalSection( &pQData->cSection );
270 nCaptureHT = pQData->nCaptureHT;
271 LeaveCriticalSection( &pQData->cSection );
272
273 return nCaptureHT;
274}
275
276
277/***********************************************************************
278 * PERQDATA_SetCaptureInfo
279 *
280 * Set the capture info member in a threadsafe manner
281 */
282INT16 PERQDATA_SetCaptureInfo( PERQUEUEDATA *pQData, INT16 nCaptureHT )
283{
284 INT16 nCaptureHTPrv;
285 assert(pQData != 0 );
286
287 EnterCriticalSection( &pQData->cSection );
288 nCaptureHTPrv = pQData->nCaptureHT;
289 pQData->nCaptureHT = nCaptureHT;
290 LeaveCriticalSection( &pQData->cSection );
291
292 return nCaptureHTPrv;
293}
294
295
296/***********************************************************************
Stephane Lussier1c4786f1999-01-28 10:54:11 +0000297 * QUEUE_Lock
298 *
Noel Borthwickb4278561999-02-05 10:37:53 +0000299 * Function for getting a 32 bit pointer on queue strcture. For thread
Stephane Lussier1c4786f1999-01-28 10:54:11 +0000300 * safeness programmers should use this function instead of GlobalLock to
301 * retrieve a pointer on the structure. QUEUE_Unlock should also be called
302 * when access to the queue structure is not required anymore.
303 */
304MESSAGEQUEUE *QUEUE_Lock( HQUEUE16 hQueue )
305{
306 MESSAGEQUEUE *queue;
307
Alexandre Julliard34bf8151999-03-21 08:36:55 +0000308 HeapLock( SystemHeap ); /* FIXME: a bit overkill */
Stephane Lussier1c4786f1999-01-28 10:54:11 +0000309 queue = GlobalLock16( hQueue );
310 if ( !queue || (queue->magic != QUEUE_MAGIC) )
311 {
Alexandre Julliard34bf8151999-03-21 08:36:55 +0000312 HeapUnlock( SystemHeap );
Stephane Lussier1c4786f1999-01-28 10:54:11 +0000313 return NULL;
314 }
315
316 queue->lockCount++;
Alexandre Julliard34bf8151999-03-21 08:36:55 +0000317 HeapUnlock( SystemHeap );
Stephane Lussier1c4786f1999-01-28 10:54:11 +0000318 return queue;
319}
320
Noel Borthwickb4278561999-02-05 10:37:53 +0000321
Stephane Lussier1c4786f1999-01-28 10:54:11 +0000322/***********************************************************************
323 * QUEUE_Unlock
324 *
325 * Use with QUEUE_Lock to get a thread safe acces to message queue
326 * structure
327 */
328void QUEUE_Unlock( MESSAGEQUEUE *queue )
329{
330 if (queue)
331 {
Alexandre Julliard34bf8151999-03-21 08:36:55 +0000332 HeapLock( SystemHeap ); /* FIXME: a bit overkill */
Stephane Lussier1c4786f1999-01-28 10:54:11 +0000333
334 if ( --queue->lockCount == 0 )
335 {
336 DeleteCriticalSection ( &queue->cSection );
Stephane Lussierb3a99de1999-02-09 15:35:12 +0000337 if (queue->hEvent)
338 CloseHandle( queue->hEvent );
Stephane Lussier1c4786f1999-01-28 10:54:11 +0000339 GlobalFree16( queue->self );
340 }
341
Alexandre Julliard34bf8151999-03-21 08:36:55 +0000342 HeapUnlock( SystemHeap );
Stephane Lussier1c4786f1999-01-28 10:54:11 +0000343 }
344}
345
Alexandre Julliardb817f4f1996-03-14 18:08:34 +0000346
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000347/***********************************************************************
Alexandre Julliardb817f4f1996-03-14 18:08:34 +0000348 * QUEUE_DumpQueue
349 */
Alexandre Julliardca22b331996-07-12 19:02:39 +0000350void QUEUE_DumpQueue( HQUEUE16 hQueue )
Alexandre Julliardb817f4f1996-03-14 18:08:34 +0000351{
352 MESSAGEQUEUE *pq;
353
Stephane Lussier1c4786f1999-01-28 10:54:11 +0000354 if (!(pq = (MESSAGEQUEUE*) QUEUE_Lock( hQueue )) )
Alexandre Julliardb817f4f1996-03-14 18:08:34 +0000355 {
Alexandre Julliarda845b881998-06-01 10:44:35 +0000356 WARN(msg, "%04x is not a queue handle\n", hQueue );
Alexandre Julliardb817f4f1996-03-14 18:08:34 +0000357 return;
358 }
359
Alexandre Julliarda845b881998-06-01 10:44:35 +0000360 DUMP( "next: %12.4x Intertask SendMessage:\n"
Stephane Lussiera4c84451999-01-26 09:30:05 +0000361 "thread: %10p ----------------------\n"
Stephane Lussier2c86dab1999-02-18 17:34:09 +0000362 "firstMsg: %8p smWaiting: %10p\n"
363 "lastMsg: %8p smPending: %10p\n"
364 "msgCount: %8.4x smProcessing: %10p\n"
365 "lockCount: %7.4x\n"
366 "wWinVer: %9.4x\n"
367 "paints: %10.4x\n"
368 "timers: %10.4x\n"
Alexandre Julliardb817f4f1996-03-14 18:08:34 +0000369 "wakeBits: %8.4x\n"
370 "wakeMask: %8.4x\n"
371 "hCurHook: %8.4x\n",
Stephane Lussier2c86dab1999-02-18 17:34:09 +0000372 pq->next, pq->thdb, pq->firstMsg, pq->smWaiting, pq->lastMsg,
373 pq->smPending, pq->msgCount, pq->smProcessing,
374 (unsigned)pq->lockCount, pq->wWinVersion,
375 pq->wPaintCount, pq->wTimerCount,
376 pq->wakeBits, pq->wakeMask, pq->hCurHook);
Stephane Lussier1c4786f1999-01-28 10:54:11 +0000377
378 QUEUE_Unlock( pq );
Alexandre Julliardb817f4f1996-03-14 18:08:34 +0000379}
380
381
382/***********************************************************************
383 * QUEUE_WalkQueues
384 */
385void QUEUE_WalkQueues(void)
386{
Alexandre Julliarddadf78f1998-05-17 17:13:43 +0000387 char module[10];
Alexandre Julliard8cc3a5e1996-08-11 15:49:51 +0000388 HQUEUE16 hQueue = hFirstQueue;
Alexandre Julliardb817f4f1996-03-14 18:08:34 +0000389
Stephane Lussiera4c84451999-01-26 09:30:05 +0000390 DUMP( "Queue Msgs Thread Task Module\n" );
Alexandre Julliardb817f4f1996-03-14 18:08:34 +0000391 while (hQueue)
392 {
Stephane Lussier1c4786f1999-01-28 10:54:11 +0000393 MESSAGEQUEUE *queue = (MESSAGEQUEUE *)QUEUE_Lock( hQueue );
Alexandre Julliardb817f4f1996-03-14 18:08:34 +0000394 if (!queue)
395 {
Alexandre Julliarda845b881998-06-01 10:44:35 +0000396 WARN( msg, "Bad queue handle %04x\n", hQueue );
Alexandre Julliardb817f4f1996-03-14 18:08:34 +0000397 return;
398 }
Alexandre Julliarda3960291999-02-26 11:11:13 +0000399 if (!GetModuleName16( queue->thdb->process->task, module, sizeof(module )))
Alexandre Julliarddadf78f1998-05-17 17:13:43 +0000400 strcpy( module, "???" );
Stephane Lussiera4c84451999-01-26 09:30:05 +0000401 DUMP( "%04x %4d %p %04x %s\n", hQueue,queue->msgCount,
402 queue->thdb, queue->thdb->process->task, module );
Alexandre Julliardb817f4f1996-03-14 18:08:34 +0000403 hQueue = queue->next;
Stephane Lussier1c4786f1999-01-28 10:54:11 +0000404 QUEUE_Unlock( queue );
Alexandre Julliardb817f4f1996-03-14 18:08:34 +0000405 }
Alexandre Julliarda845b881998-06-01 10:44:35 +0000406 DUMP( "\n" );
Alexandre Julliardb817f4f1996-03-14 18:08:34 +0000407}
408
409
410/***********************************************************************
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000411 * QUEUE_IsExitingQueue
Alexandre Julliard8cc3a5e1996-08-11 15:49:51 +0000412 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000413BOOL QUEUE_IsExitingQueue( HQUEUE16 hQueue )
Alexandre Julliard8cc3a5e1996-08-11 15:49:51 +0000414{
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000415 return (hExitingQueue && (hQueue == hExitingQueue));
Alexandre Julliard8cc3a5e1996-08-11 15:49:51 +0000416}
417
418
419/***********************************************************************
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000420 * QUEUE_SetExitingQueue
Alexandre Julliard8cc3a5e1996-08-11 15:49:51 +0000421 */
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000422void QUEUE_SetExitingQueue( HQUEUE16 hQueue )
Alexandre Julliard8cc3a5e1996-08-11 15:49:51 +0000423{
Alexandre Julliard7ff1c411997-05-25 13:58:18 +0000424 hExitingQueue = hQueue;
Alexandre Julliard8cc3a5e1996-08-11 15:49:51 +0000425}
426
427
428/***********************************************************************
Alexandre Julliardb817f4f1996-03-14 18:08:34 +0000429 * QUEUE_CreateMsgQueue
430 *
431 * Creates a message queue. Doesn't link it into queue list!
432 */
Noel Borthwickb4278561999-02-05 10:37:53 +0000433static HQUEUE16 QUEUE_CreateMsgQueue( BOOL16 bCreatePerQData )
Alexandre Julliardb817f4f1996-03-14 18:08:34 +0000434{
Alexandre Julliard8cc3a5e1996-08-11 15:49:51 +0000435 HQUEUE16 hQueue;
Alexandre Julliardb817f4f1996-03-14 18:08:34 +0000436 MESSAGEQUEUE * msgQueue;
Alexandre Julliardef702d81996-05-28 18:54:58 +0000437 TDB *pTask = (TDB *)GlobalLock16( GetCurrentTask() );
Alexandre Julliardb817f4f1996-03-14 18:08:34 +0000438
Noel Borthwickb4278561999-02-05 10:37:53 +0000439 TRACE(msg,"(): Creating message queue...\n");
Alexandre Julliard2ace16a1996-04-28 15:09:19 +0000440
Stephane Lussiera4c84451999-01-26 09:30:05 +0000441 if (!(hQueue = GlobalAlloc16( GMEM_FIXED | GMEM_ZEROINIT,
442 sizeof(MESSAGEQUEUE) )))
Alexandre Julliardb817f4f1996-03-14 18:08:34 +0000443 return 0;
Stephane Lussiera4c84451999-01-26 09:30:05 +0000444
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000445 msgQueue = (MESSAGEQUEUE *) GlobalLock16( hQueue );
Stephane Lussier1c4786f1999-01-28 10:54:11 +0000446 if ( !msgQueue )
447 return 0;
448
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000449 msgQueue->self = hQueue;
Stephane Lussier2c86dab1999-02-18 17:34:09 +0000450 msgQueue->wakeBits = msgQueue->changeBits = 0;
Alexandre Julliardef702d81996-05-28 18:54:58 +0000451 msgQueue->wWinVersion = pTask ? pTask->version : 0;
Stephane Lussier1c4786f1999-01-28 10:54:11 +0000452
453 InitializeCriticalSection( &msgQueue->cSection );
Stephane Lussier77983071999-02-13 12:24:04 +0000454 MakeCriticalSectionGlobal( &msgQueue->cSection );
Stephane Lussierb3a99de1999-02-09 15:35:12 +0000455
456 /* Create an Event object for waiting on message, used by win32 thread
457 only */
458 if ( !THREAD_IsWin16( THREAD_Current() ) )
459 {
Alexandre Julliarda3960291999-02-26 11:11:13 +0000460 msgQueue->hEvent = CreateEventA( NULL, FALSE, FALSE, NULL);
Stephane Lussierb3a99de1999-02-09 15:35:12 +0000461
462 if (msgQueue->hEvent == 0)
463 {
464 WARN(msg, "CreateEvent32A is not able to create an event object");
465 return 0;
466 }
467 msgQueue->hEvent = ConvertToGlobalHandle( msgQueue->hEvent );
468 }
469 else
470 msgQueue->hEvent = 0;
471
Stephane Lussier1c4786f1999-01-28 10:54:11 +0000472 msgQueue->lockCount = 1;
473 msgQueue->magic = QUEUE_MAGIC;
474
Noel Borthwickb4278561999-02-05 10:37:53 +0000475 /* Create and initialize our per queue data */
476 msgQueue->pQData = bCreatePerQData ? PERQDATA_CreateInstance() : NULL;
477
Alexandre Julliardb817f4f1996-03-14 18:08:34 +0000478 return hQueue;
479}
480
481
482/***********************************************************************
Stephane Lussier2c86dab1999-02-18 17:34:09 +0000483 * QUEUE_FlushMessage
484 *
485 * Try to reply to all pending sent messages on exit.
486 */
487void QUEUE_FlushMessages( MESSAGEQUEUE *queue )
488{
489 SMSG *smsg;
490 MESSAGEQUEUE *senderQ = 0;
491
492 if( queue )
493 {
494 EnterCriticalSection( &queue->cSection );
495
496 /* empty the list of pending SendMessage waiting to be received */
497 while (queue->smPending)
498 {
499 smsg = QUEUE_RemoveSMSG( queue, SM_PENDING_LIST, 0);
500
501 senderQ = (MESSAGEQUEUE*)QUEUE_Lock( smsg->hSrcQueue );
502 if ( !senderQ )
503 continue;
504
505 /* return 0, to unblock other thread */
506 smsg->lResult = 0;
507 smsg->flags |= SMSG_HAVE_RESULT;
508 QUEUE_SetWakeBit( senderQ, QS_SMRESULT);
509
510 QUEUE_Unlock( senderQ );
511 }
512
513 QUEUE_ClearWakeBit( queue, QS_SENDMESSAGE );
514
515 LeaveCriticalSection( &queue->cSection );
516 }
517}
518
519
520/***********************************************************************
Alexandre Julliardb817f4f1996-03-14 18:08:34 +0000521 * QUEUE_DeleteMsgQueue
522 *
523 * Unlinks and deletes a message queue.
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000524 *
525 * Note: We need to mask asynchronous events to make sure PostMessage works
526 * even in the signal handler.
Alexandre Julliardb817f4f1996-03-14 18:08:34 +0000527 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000528BOOL QUEUE_DeleteMsgQueue( HQUEUE16 hQueue )
Alexandre Julliardb817f4f1996-03-14 18:08:34 +0000529{
Stephane Lussier1c4786f1999-01-28 10:54:11 +0000530 MESSAGEQUEUE * msgQueue = (MESSAGEQUEUE*)QUEUE_Lock(hQueue);
Alexandre Julliard18f92e71996-07-17 20:02:21 +0000531 HQUEUE16 *pPrev;
Alexandre Julliardb817f4f1996-03-14 18:08:34 +0000532
Noel Borthwickb4278561999-02-05 10:37:53 +0000533 TRACE(msg,"(): Deleting message queue %04x\n", hQueue);
Alexandre Julliard2ace16a1996-04-28 15:09:19 +0000534
Alexandre Julliardb817f4f1996-03-14 18:08:34 +0000535 if (!hQueue || !msgQueue)
536 {
Alexandre Julliarda69b88b1998-03-15 20:29:56 +0000537 WARN(msg, "invalid argument.\n");
Alexandre Julliardb817f4f1996-03-14 18:08:34 +0000538 return 0;
539 }
Stephane Lussier1c4786f1999-01-28 10:54:11 +0000540
541 msgQueue->magic = 0;
542
543 if( hCursorQueue == hQueue ) hCursorQueue = 0;
544 if( hActiveQueue == hQueue ) hActiveQueue = 0;
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000545
546 /* flush sent messages */
Stephane Lussier2c86dab1999-02-18 17:34:09 +0000547 QUEUE_FlushMessages( msgQueue );
Alexandre Julliardb817f4f1996-03-14 18:08:34 +0000548
Alexandre Julliard34bf8151999-03-21 08:36:55 +0000549 HeapLock( SystemHeap ); /* FIXME: a bit overkill */
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000550
Noel Borthwickb4278561999-02-05 10:37:53 +0000551 /* Release per queue data if present */
552 if ( msgQueue->pQData )
553 {
554 PERQDATA_Release( msgQueue->pQData );
555 msgQueue->pQData = 0;
556 }
557
Stephane Lussier1c4786f1999-01-28 10:54:11 +0000558 /* remove the message queue from the global link list */
Alexandre Julliardb817f4f1996-03-14 18:08:34 +0000559 pPrev = &hFirstQueue;
560 while (*pPrev && (*pPrev != hQueue))
561 {
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000562 MESSAGEQUEUE *msgQ = (MESSAGEQUEUE*)GlobalLock16(*pPrev);
Stephane Lussier91bb1f91999-02-09 14:07:07 +0000563
564 /* sanity check */
565 if ( !msgQ || (msgQ->magic != QUEUE_MAGIC) )
566 {
567 /* HQUEUE link list is corrupted, try to exit gracefully */
568 WARN( msg, "HQUEUE link list corrupted!\n");
569 pPrev = 0;
570 break;
571 }
Alexandre Julliardb817f4f1996-03-14 18:08:34 +0000572 pPrev = &msgQ->next;
573 }
Stephane Lussier91bb1f91999-02-09 14:07:07 +0000574 if (pPrev && *pPrev) *pPrev = msgQueue->next;
Alexandre Julliard8b915631996-06-16 16:16:05 +0000575 msgQueue->self = 0;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000576
Alexandre Julliard34bf8151999-03-21 08:36:55 +0000577 HeapUnlock( SystemHeap );
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000578
Stephane Lussier1c4786f1999-01-28 10:54:11 +0000579 /* free up resource used by MESSAGEQUEUE strcture */
580 msgQueue->lockCount--;
581 QUEUE_Unlock( msgQueue );
582
Alexandre Julliardb817f4f1996-03-14 18:08:34 +0000583 return 1;
584}
585
586
587/***********************************************************************
588 * QUEUE_CreateSysMsgQueue
589 *
590 * Create the system message queue, and set the double-click speed.
591 * Must be called only once.
592 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000593BOOL QUEUE_CreateSysMsgQueue( int size )
Alexandre Julliardb817f4f1996-03-14 18:08:34 +0000594{
Noel Borthwickb4278561999-02-05 10:37:53 +0000595 /* Note: We dont need perQ data for the system message queue */
596 if (!(hmemSysMsgQueue = QUEUE_CreateMsgQueue( FALSE )))
597 return FALSE;
598
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000599 sysMsgQueue = (MESSAGEQUEUE *) GlobalLock16( hmemSysMsgQueue );
Alexandre Julliardb817f4f1996-03-14 18:08:34 +0000600 return TRUE;
601}
602
603
604/***********************************************************************
605 * QUEUE_GetSysQueue
606 */
607MESSAGEQUEUE *QUEUE_GetSysQueue(void)
608{
609 return sysMsgQueue;
610}
611
Alexandre Julliard85ed45e1998-08-22 19:03:56 +0000612
613/***********************************************************************
Stephane Lussier91bb1f91999-02-09 14:07:07 +0000614 * QUEUE_SetWakeBit
Alexandre Julliardef702d81996-05-28 18:54:58 +0000615 *
616 * See "Windows Internals", p.449
617 */
618void QUEUE_SetWakeBit( MESSAGEQUEUE *queue, WORD bit )
619{
Alexandre Julliarda69b88b1998-03-15 20:29:56 +0000620 TRACE(msg,"queue = %04x (wm=%04x), bit = %04x\n",
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000621 queue->self, queue->wakeMask, bit );
622
Alexandre Julliard8b915631996-06-16 16:16:05 +0000623 if (bit & QS_MOUSE) pMouseQueue = queue;
624 if (bit & QS_KEY) pKbdQueue = queue;
Alexandre Julliardef702d81996-05-28 18:54:58 +0000625 queue->changeBits |= bit;
626 queue->wakeBits |= bit;
627 if (queue->wakeMask & bit)
628 {
629 queue->wakeMask = 0;
Stephane Lussierb3a99de1999-02-09 15:35:12 +0000630
631 /* Wake up thread waiting for message */
632 if ( THREAD_IsWin16( queue->thdb ) )
Alexandre Julliarda3960291999-02-26 11:11:13 +0000633 PostEvent16( queue->thdb->process->task );
Stephane Lussierb3a99de1999-02-09 15:35:12 +0000634 else
635 {
636 SetEvent( queue->hEvent );
637 }
Alexandre Julliardef702d81996-05-28 18:54:58 +0000638 }
639}
640
641
642/***********************************************************************
Alexandre Julliard8b915631996-06-16 16:16:05 +0000643 * QUEUE_ClearWakeBit
644 */
645void QUEUE_ClearWakeBit( MESSAGEQUEUE *queue, WORD bit )
646{
647 queue->changeBits &= ~bit;
648 queue->wakeBits &= ~bit;
649}
650
651
652/***********************************************************************
Alexandre Julliardef702d81996-05-28 18:54:58 +0000653 * QUEUE_WaitBits
654 *
655 * See "Windows Internals", p.447
Stephane Lussierbae55521999-03-10 16:21:12 +0000656 *
657 * return values:
658 * 0 if exit with timeout
659 * 1 otherwise
Alexandre Julliardef702d81996-05-28 18:54:58 +0000660 */
Stephane Lussierbae55521999-03-10 16:21:12 +0000661int QUEUE_WaitBits( WORD bits, DWORD timeout )
Alexandre Julliardef702d81996-05-28 18:54:58 +0000662{
663 MESSAGEQUEUE *queue;
Stephane Lussierbae55521999-03-10 16:21:12 +0000664 DWORD curTime = 0;
Alexandre Julliardef702d81996-05-28 18:54:58 +0000665
Alexandre Julliarda3960291999-02-26 11:11:13 +0000666 TRACE(msg,"q %04x waiting for %04x\n", GetFastQueue16(), bits);
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000667
Stephane Lussierbae55521999-03-10 16:21:12 +0000668 if ( THREAD_IsWin16( THREAD_Current() ) && (timeout != INFINITE) )
669 curTime = GetTickCount();
670
671 if (!(queue = (MESSAGEQUEUE *)QUEUE_Lock( GetFastQueue16() ))) return 0;
672
Alexandre Julliardef702d81996-05-28 18:54:58 +0000673 for (;;)
674 {
Alexandre Julliardef702d81996-05-28 18:54:58 +0000675 if (queue->changeBits & bits)
676 {
677 /* One of the bits is set; we can return */
678 queue->wakeMask = 0;
Stephane Lussier1c4786f1999-01-28 10:54:11 +0000679 QUEUE_Unlock( queue );
Stephane Lussierbae55521999-03-10 16:21:12 +0000680 return 1;
Alexandre Julliardef702d81996-05-28 18:54:58 +0000681 }
682 if (queue->wakeBits & QS_SENDMESSAGE)
683 {
684 /* Process the sent message immediately */
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000685
686 queue->wakeMask = 0;
Alexandre Julliardef702d81996-05-28 18:54:58 +0000687 QUEUE_ReceiveMessage( queue );
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000688 continue; /* nested sm crux */
Alexandre Julliardef702d81996-05-28 18:54:58 +0000689 }
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000690
Alexandre Julliardef702d81996-05-28 18:54:58 +0000691 queue->wakeMask = bits | QS_SENDMESSAGE;
Stephane Lussier1c4786f1999-01-28 10:54:11 +0000692 if(queue->changeBits & bits)
693 {
Stephane Lussier1c4786f1999-01-28 10:54:11 +0000694 continue;
695 }
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000696
Alexandre Julliarda69b88b1998-03-15 20:29:56 +0000697 TRACE(msg,"%04x) wakeMask is %04x, waiting\n", queue->self, queue->wakeMask);
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000698
Stephane Lussierbae55521999-03-10 16:21:12 +0000699 if ( !THREAD_IsWin16( THREAD_Current() ) )
700 {
701 /* win32 thread, use WaitForMultipleObjects */
702 MsgWaitForMultipleObjects( 0, NULL, FALSE, timeout, queue->wakeMask );
703 }
704 else
705 {
706 if ( timeout == INFINITE )
707 WaitEvent16( 0 ); /* win 16 thread, use WaitEvent */
708 else
709 {
710 /* check for timeout, then give control to other tasks */
711 if (GetTickCount() - curTime > timeout)
712 {
Stephane Lussier1c4786f1999-01-28 10:54:11 +0000713
714 QUEUE_Unlock( queue );
Stephane Lussierbae55521999-03-10 16:21:12 +0000715 return 0; /* exit with timeout */
716 }
717 Yield16();
718 }
Alexandre Julliardef702d81996-05-28 18:54:58 +0000719 }
720}
Stephane Lussierbae55521999-03-10 16:21:12 +0000721}
Alexandre Julliardef702d81996-05-28 18:54:58 +0000722
723
724/***********************************************************************
Stephane Lussier2c86dab1999-02-18 17:34:09 +0000725 * QUEUE_AddSMSG
Alexandre Julliardef702d81996-05-28 18:54:58 +0000726 *
Stephane Lussier2c86dab1999-02-18 17:34:09 +0000727 * This routine is called when a SMSG need to be added to one of the three
728 * SM list. (SM_PROCESSING_LIST, SM_PENDING_LIST, SM_WAITING_LIST)
729 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000730BOOL QUEUE_AddSMSG( MESSAGEQUEUE *queue, int list, SMSG *smsg )
Stephane Lussier2c86dab1999-02-18 17:34:09 +0000731{
732 TRACE(sendmsg,"queue=%x, list=%d, smsg=%p msg=%s\n", queue->self, list,
733 smsg, SPY_GetMsgName(smsg->msg));
734
735 switch (list)
736 {
737 case SM_PROCESSING_LIST:
738 /* don't need to be thread safe, only accessed by the
739 thread associated with the sender queue */
740 smsg->nextProcessing = queue->smProcessing;
741 queue->smProcessing = smsg;
742 break;
743
744 case SM_WAITING_LIST:
745 /* don't need to be thread safe, only accessed by the
746 thread associated with the receiver queue */
747 smsg->nextWaiting = queue->smWaiting;
748 queue->smWaiting = smsg;
749 break;
750
751 case SM_PENDING_LIST:
Ulrich Weigandc68c4b11999-03-17 15:14:31 +0000752 {
Stephane Lussier2c86dab1999-02-18 17:34:09 +0000753 /* make it thread safe, could be accessed by the sender and
754 receiver thread */
Ulrich Weigandc68c4b11999-03-17 15:14:31 +0000755 SMSG **prev;
Stephane Lussier2c86dab1999-02-18 17:34:09 +0000756
757 EnterCriticalSection( &queue->cSection );
Ulrich Weigandc68c4b11999-03-17 15:14:31 +0000758 smsg->nextPending = NULL;
759 prev = &queue->smPending;
760 while ( *prev )
761 prev = &(*prev)->nextPending;
762 *prev = smsg;
Stephane Lussier2c86dab1999-02-18 17:34:09 +0000763 LeaveCriticalSection( &queue->cSection );
Ulrich Weigandc68c4b11999-03-17 15:14:31 +0000764
765 QUEUE_SetWakeBit( queue, QS_SENDMESSAGE );
Stephane Lussier2c86dab1999-02-18 17:34:09 +0000766 break;
Ulrich Weigandc68c4b11999-03-17 15:14:31 +0000767 }
Stephane Lussier2c86dab1999-02-18 17:34:09 +0000768
769 default:
770 WARN(sendmsg, "Invalid list: %d", list);
771 break;
772 }
773
774 return TRUE;
775}
776
777
778/***********************************************************************
779 * QUEUE_RemoveSMSG
780 *
781 * This routine is called when a SMSG need to be remove from one of the three
782 * SM list. (SM_PROCESSING_LIST, SM_PENDING_LIST, SM_WAITING_LIST)
783 * If smsg == 0, remove the first smsg from the specified list
784 */
785SMSG *QUEUE_RemoveSMSG( MESSAGEQUEUE *queue, int list, SMSG *smsg )
786{
787
788 switch (list)
789 {
790 case SM_PROCESSING_LIST:
791 /* don't need to be thread safe, only accessed by the
792 thread associated with the sender queue */
793
794 /* if smsg is equal to null, it means the first in the list */
795 if (!smsg)
796 smsg = queue->smProcessing;
797
798 TRACE(sendmsg,"queue=%x, list=%d, smsg=%p msg=%s\n", queue->self, list,
799 smsg, SPY_GetMsgName(smsg->msg));
800 /* In fact SM_PROCESSING_LIST is a stack, and smsg
801 should be always at the top of the list */
802 if ( (smsg != queue->smProcessing) || !queue->smProcessing )
803 {
804 ERR( sendmsg, "smsg not at the top of Processing list, smsg=0x%p queue=0x%p", smsg, queue);
805 return 0;
806 }
807 else
808 {
809 queue->smProcessing = smsg->nextProcessing;
810 smsg->nextProcessing = 0;
811 }
812 return smsg;
813
814 case SM_WAITING_LIST:
815 /* don't need to be thread safe, only accessed by the
816 thread associated with the receiver queue */
817
818 /* if smsg is equal to null, it means the first in the list */
819 if (!smsg)
820 smsg = queue->smWaiting;
821
822 TRACE(sendmsg,"queue=%x, list=%d, smsg=%p msg=%s\n", queue->self, list,
823 smsg, SPY_GetMsgName(smsg->msg));
824 /* In fact SM_WAITING_LIST is a stack, and smsg
825 should be always at the top of the list */
826 if ( (smsg != queue->smWaiting) || !queue->smWaiting )
827 {
828 ERR( sendmsg, "smsg not at the top of Waiting list, smsg=0x%p queue=0x%p", smsg, queue);
829 return 0;
830 }
831 else
832 {
833 queue->smWaiting = smsg->nextWaiting;
834 smsg->nextWaiting = 0;
835 }
836 return smsg;
837
838 case SM_PENDING_LIST:
839 /* make it thread safe, could be accessed by the sender and
840 receiver thread */
841 EnterCriticalSection( &queue->cSection );
842
843 if (!smsg || !queue->smPending)
844 smsg = queue->smPending;
845 else
846 {
847 ERR( sendmsg, "should always remove the top one in Pending list, smsg=0x%p queue=0x%p", smsg, queue);
848 return 0;
849 }
850
851 TRACE(sendmsg,"queue=%x, list=%d, smsg=%p msg=%s\n", queue->self, list,
852 smsg, SPY_GetMsgName(smsg->msg));
853
854 queue->smPending = smsg->nextPending;
855 smsg->nextPending = 0;
856
857 /* if no more SMSG in Pending list, clear QS_SENDMESSAGE flag */
858 if (!queue->smPending)
859 QUEUE_ClearWakeBit( queue, QS_SENDMESSAGE );
860
861 LeaveCriticalSection( &queue->cSection );
862 return smsg;
863
864 default:
865 WARN(sendmsg, "Invalid list: %d", list);
866 break;
867 }
868
869 return 0;
870}
871
872
873/***********************************************************************
874 * QUEUE_ReceiveMessage
875 *
Alexandre Julliardef702d81996-05-28 18:54:58 +0000876 * This routine is called when a sent message is waiting for the queue.
877 */
878void QUEUE_ReceiveMessage( MESSAGEQUEUE *queue )
879{
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000880 LRESULT result = 0;
Stephane Lussier2c86dab1999-02-18 17:34:09 +0000881 SMSG *smsg;
882 MESSAGEQUEUE *senderQ;
Alexandre Julliardef702d81996-05-28 18:54:58 +0000883
Stephane Lussier2c86dab1999-02-18 17:34:09 +0000884 TRACE(sendmsg, "queue %04x\n", queue->self );
Alexandre Julliardef702d81996-05-28 18:54:58 +0000885
Stephane Lussier2c86dab1999-02-18 17:34:09 +0000886 if ( !(queue->wakeBits & QS_SENDMESSAGE) && queue->smPending )
Alexandre Julliard8b915631996-06-16 16:16:05 +0000887 {
Stephane Lussier2c86dab1999-02-18 17:34:09 +0000888 TRACE(sendmsg,"\trcm: nothing to do\n");
889 return;
890 }
Alexandre Julliardef702d81996-05-28 18:54:58 +0000891
Stephane Lussier2c86dab1999-02-18 17:34:09 +0000892 /* remove smsg on the top of the pending list and put it in the processing list */
893 smsg = QUEUE_RemoveSMSG(queue, SM_PENDING_LIST, 0);
894 QUEUE_AddSMSG(queue, SM_WAITING_LIST, smsg);
895
896 TRACE(sendmsg,"RM: %s [%04x] (%04x -> %04x)\n",
897 SPY_GetMsgName(smsg->msg), smsg->msg, smsg->hSrcQueue, smsg->hDstQueue );
898
Alexandre Julliarda3960291999-02-26 11:11:13 +0000899 if (IsWindow( smsg->hWnd ))
Stephane Lussier2c86dab1999-02-18 17:34:09 +0000900 {
901 WND *wndPtr = WIN_FindWndPtr( smsg->hWnd );
902 DWORD extraInfo = queue->GetMessageExtraInfoVal; /* save ExtraInfo */
903
904 /* use sender queue extra info value while calling the window proc */
905 senderQ = (MESSAGEQUEUE*)QUEUE_Lock( smsg->hSrcQueue );
906 if (senderQ)
907 {
908 queue->GetMessageExtraInfoVal = senderQ->GetMessageExtraInfoVal;
909 QUEUE_Unlock( senderQ );
910 }
911
912 /* call the right version of CallWindowProcXX */
913 if (smsg->flags & SMSG_WIN32)
Alexandre Julliardd37eb361997-07-20 16:23:21 +0000914 {
Stephane Lussier2c86dab1999-02-18 17:34:09 +0000915 TRACE(sendmsg, "\trcm: msg is Win32\n" );
916 if (smsg->flags & SMSG_UNICODE)
Alexandre Julliarda3960291999-02-26 11:11:13 +0000917 result = CallWindowProcW( wndPtr->winproc,
Stephane Lussier2c86dab1999-02-18 17:34:09 +0000918 smsg->hWnd, smsg->msg,
919 smsg->wParam, smsg->lParam );
Alexandre Julliardd37eb361997-07-20 16:23:21 +0000920 else
Alexandre Julliarda3960291999-02-26 11:11:13 +0000921 result = CallWindowProcA( wndPtr->winproc,
Stephane Lussier2c86dab1999-02-18 17:34:09 +0000922 smsg->hWnd, smsg->msg,
923 smsg->wParam, smsg->lParam );
Alexandre Julliardd37eb361997-07-20 16:23:21 +0000924 }
925 else /* Win16 message */
926 result = CallWindowProc16( (WNDPROC16)wndPtr->winproc,
Stephane Lussier2c86dab1999-02-18 17:34:09 +0000927 (HWND16) smsg->hWnd,
928 (UINT16) smsg->msg,
929 LOWORD (smsg->wParam),
930 smsg->lParam );
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000931
932 queue->GetMessageExtraInfoVal = extraInfo; /* Restore extra info */
Francois Boisvert6b1b41c1999-03-14 17:25:32 +0000933 WIN_ReleaseWndPtr(wndPtr);
Stephane Lussier2c86dab1999-02-18 17:34:09 +0000934 TRACE(sendmsg,"result = %08x\n", (unsigned)result );
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000935 }
Stephane Lussier2c86dab1999-02-18 17:34:09 +0000936 else WARN(sendmsg, "\trcm: bad hWnd\n");
Alexandre Julliardef702d81996-05-28 18:54:58 +0000937
Stephane Lussier1c4786f1999-01-28 10:54:11 +0000938
Stephane Lussier2c86dab1999-02-18 17:34:09 +0000939 /* set SMSG_SENDING_REPLY flag to tell ReplyMessage16, it's not
940 an early reply */
941 smsg->flags |= SMSG_SENDING_REPLY;
Alexandre Julliarda3960291999-02-26 11:11:13 +0000942 ReplyMessage( result );
Stephane Lussier1c4786f1999-01-28 10:54:11 +0000943
Stephane Lussier2c86dab1999-02-18 17:34:09 +0000944 TRACE( sendmsg,"done! \n" );
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000945}
Alexandre Julliardef702d81996-05-28 18:54:58 +0000946
Stephane Lussier2c86dab1999-02-18 17:34:09 +0000947
948
Alexandre Julliardef702d81996-05-28 18:54:58 +0000949/***********************************************************************
Alexandre Julliardb817f4f1996-03-14 18:08:34 +0000950 * QUEUE_AddMsg
951 *
952 * Add a message to the queue. Return FALSE if queue is full.
953 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000954BOOL QUEUE_AddMsg( HQUEUE16 hQueue, MSG *msg, DWORD extraInfo )
Alexandre Julliardb817f4f1996-03-14 18:08:34 +0000955{
Alexandre Julliardb817f4f1996-03-14 18:08:34 +0000956 MESSAGEQUEUE *msgQueue;
Stephane Lussiera4c84451999-01-26 09:30:05 +0000957 QMSG *qmsg;
Alexandre Julliardb817f4f1996-03-14 18:08:34 +0000958
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000959
Stephane Lussier1c4786f1999-01-28 10:54:11 +0000960 if (!(msgQueue = (MESSAGEQUEUE *)QUEUE_Lock( hQueue ))) return FALSE;
Alexandre Julliardb817f4f1996-03-14 18:08:34 +0000961
Stephane Lussiera4c84451999-01-26 09:30:05 +0000962 /* allocate new message in global heap for now */
963 if (!(qmsg = (QMSG *) HeapAlloc( SystemHeap, 0, sizeof(QMSG) ) ))
Stephane Lussier1c4786f1999-01-28 10:54:11 +0000964 {
965 QUEUE_Unlock( msgQueue );
Stephane Lussiera4c84451999-01-26 09:30:05 +0000966 return 0;
Stephane Lussier1c4786f1999-01-28 10:54:11 +0000967 }
Stephane Lussiera4c84451999-01-26 09:30:05 +0000968
969 EnterCriticalSection( &msgQueue->cSection );
Alexandre Julliardb817f4f1996-03-14 18:08:34 +0000970
971 /* Store message */
Stephane Lussiera4c84451999-01-26 09:30:05 +0000972 qmsg->msg = *msg;
973 qmsg->extraInfo = extraInfo;
974
975 /* insert the message in the link list */
976 qmsg->nextMsg = 0;
977 qmsg->prevMsg = msgQueue->lastMsg;
978
979 if (msgQueue->lastMsg)
980 msgQueue->lastMsg->nextMsg = qmsg;
981
982 /* update first and last anchor in message queue */
983 msgQueue->lastMsg = qmsg;
984 if (!msgQueue->firstMsg)
985 msgQueue->firstMsg = qmsg;
986
Alexandre Julliardb817f4f1996-03-14 18:08:34 +0000987 msgQueue->msgCount++;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000988
Stephane Lussiera4c84451999-01-26 09:30:05 +0000989 LeaveCriticalSection( &msgQueue->cSection );
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000990
Alexandre Julliardef702d81996-05-28 18:54:58 +0000991 QUEUE_SetWakeBit( msgQueue, QS_POSTMESSAGE );
Stephane Lussier1c4786f1999-01-28 10:54:11 +0000992 QUEUE_Unlock( msgQueue );
993
Alexandre Julliardb817f4f1996-03-14 18:08:34 +0000994 return TRUE;
995}
996
997
Stephane Lussiera4c84451999-01-26 09:30:05 +0000998
Alexandre Julliardb817f4f1996-03-14 18:08:34 +0000999/***********************************************************************
1000 * QUEUE_FindMsg
1001 *
1002 * Find a message matching the given parameters. Return -1 if none available.
1003 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001004QMSG* QUEUE_FindMsg( MESSAGEQUEUE * msgQueue, HWND hwnd, int first, int last )
Alexandre Julliardb817f4f1996-03-14 18:08:34 +00001005{
Stephane Lussiera4c84451999-01-26 09:30:05 +00001006 QMSG* qmsg;
Alexandre Julliardb817f4f1996-03-14 18:08:34 +00001007
Stephane Lussiera4c84451999-01-26 09:30:05 +00001008 EnterCriticalSection( &msgQueue->cSection );
Alexandre Julliardb817f4f1996-03-14 18:08:34 +00001009
Stephane Lussiera4c84451999-01-26 09:30:05 +00001010 if (!msgQueue->msgCount)
1011 qmsg = 0;
1012 else if (!hwnd && !first && !last)
1013 qmsg = msgQueue->firstMsg;
1014 else
Alexandre Julliardb817f4f1996-03-14 18:08:34 +00001015 {
Stephane Lussiera4c84451999-01-26 09:30:05 +00001016 /* look in linked list for message matching first and last criteria */
1017 for (qmsg = msgQueue->firstMsg; qmsg; qmsg = qmsg->nextMsg)
1018 {
Alexandre Julliarda3960291999-02-26 11:11:13 +00001019 MSG *msg = &(qmsg->msg);
Alexandre Julliardb817f4f1996-03-14 18:08:34 +00001020
1021 if (!hwnd || (msg->hwnd == hwnd))
1022 {
Stephane Lussiera4c84451999-01-26 09:30:05 +00001023 if (!first && !last)
1024 break; /* found it */
1025
Martin Walker4d1d3591999-02-19 16:50:24 +00001026 if ((msg->message >= first) && (!last || (msg->message <= last)))
Stephane Lussiera4c84451999-01-26 09:30:05 +00001027 break; /* found it */
1028 }
Alexandre Julliardb817f4f1996-03-14 18:08:34 +00001029 }
Alexandre Julliardb817f4f1996-03-14 18:08:34 +00001030 }
Stephane Lussiera4c84451999-01-26 09:30:05 +00001031
1032 LeaveCriticalSection( &msgQueue->cSection );
1033
1034 return qmsg;
Alexandre Julliardb817f4f1996-03-14 18:08:34 +00001035}
1036
1037
Stephane Lussiera4c84451999-01-26 09:30:05 +00001038
Alexandre Julliardb817f4f1996-03-14 18:08:34 +00001039/***********************************************************************
1040 * QUEUE_RemoveMsg
1041 *
1042 * Remove a message from the queue (pos must be a valid position).
1043 */
Stephane Lussiera4c84451999-01-26 09:30:05 +00001044void QUEUE_RemoveMsg( MESSAGEQUEUE * msgQueue, QMSG *qmsg )
Alexandre Julliardb817f4f1996-03-14 18:08:34 +00001045{
Stephane Lussiera4c84451999-01-26 09:30:05 +00001046 EnterCriticalSection( &msgQueue->cSection );
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001047
Stephane Lussiera4c84451999-01-26 09:30:05 +00001048 /* set the linked list */
1049 if (qmsg->prevMsg)
1050 qmsg->prevMsg->nextMsg = qmsg->nextMsg;
1051
1052 if (qmsg->nextMsg)
1053 qmsg->nextMsg->prevMsg = qmsg->prevMsg;
1054
1055 if (msgQueue->firstMsg == qmsg)
1056 msgQueue->firstMsg = qmsg->nextMsg;
1057
1058 if (msgQueue->lastMsg == qmsg)
1059 msgQueue->lastMsg = qmsg->prevMsg;
1060
1061 /* deallocate the memory for the message */
1062 HeapFree( SystemHeap, 0, qmsg );
1063
Alexandre Julliardb817f4f1996-03-14 18:08:34 +00001064 msgQueue->msgCount--;
Alexandre Julliardef702d81996-05-28 18:54:58 +00001065 if (!msgQueue->msgCount) msgQueue->wakeBits &= ~QS_POSTMESSAGE;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001066
Stephane Lussiera4c84451999-01-26 09:30:05 +00001067 LeaveCriticalSection( &msgQueue->cSection );
Alexandre Julliardef702d81996-05-28 18:54:58 +00001068}
1069
1070
1071/***********************************************************************
1072 * QUEUE_WakeSomeone
1073 *
1074 * Wake a queue upon reception of a hardware event.
1075 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001076static void QUEUE_WakeSomeone( UINT message )
Alexandre Julliardef702d81996-05-28 18:54:58 +00001077{
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +00001078 WND* wndPtr = NULL;
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +00001079 WORD wakeBit;
Alexandre Julliarda3960291999-02-26 11:11:13 +00001080 HWND hwnd;
Stephane Lussier1c4786f1999-01-28 10:54:11 +00001081 HQUEUE16 hQueue = 0;
1082 MESSAGEQUEUE *queue = NULL;
1083
1084 if (hCursorQueue)
1085 hQueue = hCursorQueue;
Alexandre Julliardef702d81996-05-28 18:54:58 +00001086
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +00001087 if( (message >= WM_KEYFIRST) && (message <= WM_KEYLAST) )
1088 {
1089 wakeBit = QS_KEY;
Stephane Lussier1c4786f1999-01-28 10:54:11 +00001090 if( hActiveQueue )
1091 hQueue = hActiveQueue;
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +00001092 }
1093 else
1094 {
1095 wakeBit = (message == WM_MOUSEMOVE) ? QS_MOUSEMOVE : QS_MOUSEBUTTON;
Alexandre Julliarda3960291999-02-26 11:11:13 +00001096 if( (hwnd = GetCapture()) )
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +00001097 if( (wndPtr = WIN_FindWndPtr( hwnd )) )
Stephane Lussier1c4786f1999-01-28 10:54:11 +00001098 {
1099 hQueue = wndPtr->hmemTaskQ;
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00001100 WIN_ReleaseWndPtr(wndPtr);
Stephane Lussier1c4786f1999-01-28 10:54:11 +00001101 }
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +00001102 }
Alexandre Julliardef702d81996-05-28 18:54:58 +00001103
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +00001104 if( (hwnd = GetSysModalWindow16()) )
Stephane Lussier1c4786f1999-01-28 10:54:11 +00001105 {
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +00001106 if( (wndPtr = WIN_FindWndPtr( hwnd )) )
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00001107 {
Stephane Lussier1c4786f1999-01-28 10:54:11 +00001108 hQueue = wndPtr->hmemTaskQ;
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00001109 WIN_ReleaseWndPtr(wndPtr);
1110 }
Stephane Lussier1c4786f1999-01-28 10:54:11 +00001111 }
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +00001112
Stephane Lussier1c4786f1999-01-28 10:54:11 +00001113 if (hQueue)
1114 queue = QUEUE_Lock( hQueue );
1115
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +00001116 if( !queue )
Alexandre Julliardef702d81996-05-28 18:54:58 +00001117 {
Stephane Lussier1c4786f1999-01-28 10:54:11 +00001118 queue = QUEUE_Lock( hFirstQueue );
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +00001119 while( queue )
1120 {
1121 if (queue->wakeMask & wakeBit) break;
Stephane Lussier1c4786f1999-01-28 10:54:11 +00001122
1123 QUEUE_Unlock(queue);
1124 queue = QUEUE_Lock( queue->next );
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +00001125 }
1126 if( !queue )
1127 {
Alexandre Julliarda69b88b1998-03-15 20:29:56 +00001128 WARN(msg, "couldn't find queue\n");
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +00001129 return;
1130 }
Alexandre Julliardef702d81996-05-28 18:54:58 +00001131 }
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +00001132
1133 QUEUE_SetWakeBit( queue, wakeBit );
Stephane Lussier1c4786f1999-01-28 10:54:11 +00001134
1135 QUEUE_Unlock( queue );
Alexandre Julliardb817f4f1996-03-14 18:08:34 +00001136}
1137
1138
1139/***********************************************************************
1140 * hardware_event
1141 *
1142 * Add an event to the system message queue.
1143 * Note: the position is relative to the desktop window.
1144 */
1145void hardware_event( WORD message, WORD wParam, LONG lParam,
1146 int xPos, int yPos, DWORD time, DWORD extraInfo )
1147{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001148 MSG *msg;
Ulrich Weigand831560c1999-03-28 13:10:54 +00001149 QMSG *qmsg;
Stephane Lussiera4c84451999-01-26 09:30:05 +00001150 int mergeMsg = 0;
Alexandre Julliardef702d81996-05-28 18:54:58 +00001151
Alexandre Julliardb817f4f1996-03-14 18:08:34 +00001152 if (!sysMsgQueue) return;
Alexandre Julliardb817f4f1996-03-14 18:08:34 +00001153
Ulrich Weigand831560c1999-03-28 13:10:54 +00001154 EnterCriticalSection( &sysMsgQueue->cSection );
1155
1156 /* Merge with previous event if possible */
1157 qmsg = sysMsgQueue->lastMsg;
Alexandre Julliardb817f4f1996-03-14 18:08:34 +00001158
Stephane Lussiera4c84451999-01-26 09:30:05 +00001159 if ((message == WM_MOUSEMOVE) && sysMsgQueue->lastMsg)
Alexandre Julliardb817f4f1996-03-14 18:08:34 +00001160 {
Stephane Lussiera4c84451999-01-26 09:30:05 +00001161 msg = &(sysMsgQueue->lastMsg->msg);
1162
Alexandre Julliardb817f4f1996-03-14 18:08:34 +00001163 if ((msg->message == message) && (msg->wParam == wParam))
Stephane Lussiera4c84451999-01-26 09:30:05 +00001164 {
1165 /* Merge events */
1166 qmsg = sysMsgQueue->lastMsg;
1167 mergeMsg = 1;
1168 }
Alexandre Julliardb817f4f1996-03-14 18:08:34 +00001169 }
1170
Stephane Lussiera4c84451999-01-26 09:30:05 +00001171 if (!mergeMsg)
Alexandre Julliardb817f4f1996-03-14 18:08:34 +00001172 {
Stephane Lussiera4c84451999-01-26 09:30:05 +00001173 /* Should I limit the number of message in
1174 the system message queue??? */
1175
1176 /* Don't merge allocate a new msg in the global heap */
1177
1178 if (!(qmsg = (QMSG *) HeapAlloc( SystemHeap, 0, sizeof(QMSG) ) ))
Ulrich Weigand831560c1999-03-28 13:10:54 +00001179 {
1180 LeaveCriticalSection( &sysMsgQueue->cSection );
1181 return;
1182 }
Stephane Lussiera4c84451999-01-26 09:30:05 +00001183
1184 /* put message at the end of the linked list */
1185 qmsg->nextMsg = 0;
1186 qmsg->prevMsg = sysMsgQueue->lastMsg;
1187
1188 if (sysMsgQueue->lastMsg)
1189 sysMsgQueue->lastMsg->nextMsg = qmsg;
1190
1191 /* set last and first anchor index in system message queue */
1192 sysMsgQueue->lastMsg = qmsg;
1193 if (!sysMsgQueue->firstMsg)
1194 sysMsgQueue->firstMsg = qmsg;
1195
1196 sysMsgQueue->msgCount++;
Alexandre Julliardb817f4f1996-03-14 18:08:34 +00001197 }
1198
1199 /* Store message */
Stephane Lussiera4c84451999-01-26 09:30:05 +00001200 msg = &(qmsg->msg);
Alexandre Julliardb817f4f1996-03-14 18:08:34 +00001201 msg->hwnd = 0;
1202 msg->message = message;
1203 msg->wParam = wParam;
1204 msg->lParam = lParam;
1205 msg->time = time;
Stephane Lussiera4c84451999-01-26 09:30:05 +00001206 msg->pt.x = xPos;
1207 msg->pt.y = yPos;
1208 qmsg->extraInfo = extraInfo;
1209
Ulrich Weigand831560c1999-03-28 13:10:54 +00001210 LeaveCriticalSection( &sysMsgQueue->cSection );
1211
Alexandre Julliardef702d81996-05-28 18:54:58 +00001212 QUEUE_WakeSomeone( message );
Alexandre Julliardb817f4f1996-03-14 18:08:34 +00001213}
1214
1215
1216/***********************************************************************
1217 * QUEUE_GetQueueTask
1218 */
Alexandre Julliardca22b331996-07-12 19:02:39 +00001219HTASK16 QUEUE_GetQueueTask( HQUEUE16 hQueue )
Alexandre Julliardb817f4f1996-03-14 18:08:34 +00001220{
Stephane Lussier1c4786f1999-01-28 10:54:11 +00001221 HTASK16 hTask = 0;
1222
1223 MESSAGEQUEUE *queue = QUEUE_Lock( hQueue );
1224
1225 if (queue)
1226{
1227 hTask = queue->thdb->process->task;
1228 QUEUE_Unlock( queue );
Alexandre Julliardb817f4f1996-03-14 18:08:34 +00001229}
1230
Stephane Lussier1c4786f1999-01-28 10:54:11 +00001231 return hTask;
1232}
1233
1234
Alexandre Julliardb817f4f1996-03-14 18:08:34 +00001235
1236/***********************************************************************
1237 * QUEUE_IncPaintCount
1238 */
Alexandre Julliardca22b331996-07-12 19:02:39 +00001239void QUEUE_IncPaintCount( HQUEUE16 hQueue )
Alexandre Julliardb817f4f1996-03-14 18:08:34 +00001240{
1241 MESSAGEQUEUE *queue;
1242
Stephane Lussier1c4786f1999-01-28 10:54:11 +00001243 if (!(queue = (MESSAGEQUEUE *)QUEUE_Lock( hQueue ))) return;
Alexandre Julliardb817f4f1996-03-14 18:08:34 +00001244 queue->wPaintCount++;
Alexandre Julliardef702d81996-05-28 18:54:58 +00001245 QUEUE_SetWakeBit( queue, QS_PAINT );
Stephane Lussier1c4786f1999-01-28 10:54:11 +00001246 QUEUE_Unlock( queue );
Alexandre Julliardb817f4f1996-03-14 18:08:34 +00001247}
1248
1249
1250/***********************************************************************
1251 * QUEUE_DecPaintCount
1252 */
Alexandre Julliardca22b331996-07-12 19:02:39 +00001253void QUEUE_DecPaintCount( HQUEUE16 hQueue )
Alexandre Julliardb817f4f1996-03-14 18:08:34 +00001254{
1255 MESSAGEQUEUE *queue;
1256
Stephane Lussier1c4786f1999-01-28 10:54:11 +00001257 if (!(queue = (MESSAGEQUEUE *)QUEUE_Lock( hQueue ))) return;
Alexandre Julliardb817f4f1996-03-14 18:08:34 +00001258 queue->wPaintCount--;
Alexandre Julliardef702d81996-05-28 18:54:58 +00001259 if (!queue->wPaintCount) queue->wakeBits &= ~QS_PAINT;
Stephane Lussier1c4786f1999-01-28 10:54:11 +00001260 QUEUE_Unlock( queue );
Alexandre Julliardb817f4f1996-03-14 18:08:34 +00001261}
1262
1263
1264/***********************************************************************
1265 * QUEUE_IncTimerCount
1266 */
Alexandre Julliardca22b331996-07-12 19:02:39 +00001267void QUEUE_IncTimerCount( HQUEUE16 hQueue )
Alexandre Julliardb817f4f1996-03-14 18:08:34 +00001268{
1269 MESSAGEQUEUE *queue;
1270
Stephane Lussier1c4786f1999-01-28 10:54:11 +00001271 if (!(queue = (MESSAGEQUEUE *)QUEUE_Lock( hQueue ))) return;
Alexandre Julliardb817f4f1996-03-14 18:08:34 +00001272 queue->wTimerCount++;
Alexandre Julliardef702d81996-05-28 18:54:58 +00001273 QUEUE_SetWakeBit( queue, QS_TIMER );
Stephane Lussier1c4786f1999-01-28 10:54:11 +00001274 QUEUE_Unlock( queue );
Alexandre Julliardb817f4f1996-03-14 18:08:34 +00001275}
1276
1277
1278/***********************************************************************
1279 * QUEUE_DecTimerCount
1280 */
Alexandre Julliardca22b331996-07-12 19:02:39 +00001281void QUEUE_DecTimerCount( HQUEUE16 hQueue )
Alexandre Julliardb817f4f1996-03-14 18:08:34 +00001282{
1283 MESSAGEQUEUE *queue;
1284
Stephane Lussier1c4786f1999-01-28 10:54:11 +00001285 if (!(queue = (MESSAGEQUEUE *)QUEUE_Lock( hQueue ))) return;
Alexandre Julliardb817f4f1996-03-14 18:08:34 +00001286 queue->wTimerCount--;
Alexandre Julliardef702d81996-05-28 18:54:58 +00001287 if (!queue->wTimerCount) queue->wakeBits &= ~QS_TIMER;
Stephane Lussier1c4786f1999-01-28 10:54:11 +00001288 QUEUE_Unlock( queue );
Alexandre Julliardb817f4f1996-03-14 18:08:34 +00001289}
1290
1291
1292/***********************************************************************
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001293 * PostQuitMessage16 (USER.6)
Alexandre Julliardb817f4f1996-03-14 18:08:34 +00001294 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001295void WINAPI PostQuitMessage16( INT16 exitCode )
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001296{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001297 PostQuitMessage( exitCode );
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001298}
1299
1300
1301/***********************************************************************
Alexandre Julliardc7c217b1998-04-13 12:21:30 +00001302 * PostQuitMessage32 (USER32.421)
Douglas Ridgwayefaa5731998-10-25 09:20:30 +00001303 *
1304 * PostQuitMessage() posts a message to the system requesting an
1305 * application to terminate execution. As a result of this function,
1306 * the WM_QUIT message is posted to the application, and
1307 * PostQuitMessage() returns immediately. The exitCode parameter
1308 * specifies an application-defined exit code, which appears in the
1309 * _wParam_ parameter of the WM_QUIT message posted to the application.
1310 *
1311 * CONFORMANCE
1312 *
1313 * ECMA-234, Win32
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001314 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001315void WINAPI PostQuitMessage( INT exitCode )
Alexandre Julliardb817f4f1996-03-14 18:08:34 +00001316{
1317 MESSAGEQUEUE *queue;
1318
Alexandre Julliarda3960291999-02-26 11:11:13 +00001319 if (!(queue = (MESSAGEQUEUE *)QUEUE_Lock( GetFastQueue16() ))) return;
Alexandre Julliardb817f4f1996-03-14 18:08:34 +00001320 queue->wPostQMsg = TRUE;
1321 queue->wExitCode = (WORD)exitCode;
Stephane Lussier1c4786f1999-01-28 10:54:11 +00001322 QUEUE_Unlock( queue );
Alexandre Julliardb817f4f1996-03-14 18:08:34 +00001323}
1324
1325
1326/***********************************************************************
Alexandre Julliardca22b331996-07-12 19:02:39 +00001327 * GetWindowTask16 (USER.224)
Alexandre Julliardb817f4f1996-03-14 18:08:34 +00001328 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001329HTASK16 WINAPI GetWindowTask16( HWND16 hwnd )
Alexandre Julliardb817f4f1996-03-14 18:08:34 +00001330{
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00001331 HTASK16 retvalue;
Alexandre Julliardb817f4f1996-03-14 18:08:34 +00001332 WND *wndPtr = WIN_FindWndPtr( hwnd );
1333
1334 if (!wndPtr) return 0;
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00001335 retvalue = QUEUE_GetQueueTask( wndPtr->hmemTaskQ );
1336 WIN_ReleaseWndPtr(wndPtr);
1337 return retvalue;
Alexandre Julliardb817f4f1996-03-14 18:08:34 +00001338}
1339
Alexandre Julliard349a9531997-02-02 19:01:52 +00001340/***********************************************************************
Alexandre Julliardc7c217b1998-04-13 12:21:30 +00001341 * GetWindowThreadProcessId (USER32.313)
Alexandre Julliard349a9531997-02-02 19:01:52 +00001342 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001343DWORD WINAPI GetWindowThreadProcessId( HWND hwnd, LPDWORD process )
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001344{
Alexandre Julliard349a9531997-02-02 19:01:52 +00001345 HTASK16 htask;
1346 TDB *tdb;
1347
1348 WND *wndPtr = WIN_FindWndPtr( hwnd );
1349
1350 if (!wndPtr) return 0;
1351 htask=QUEUE_GetQueueTask( wndPtr->hmemTaskQ );
Francois Boisvert6b1b41c1999-03-14 17:25:32 +00001352 WIN_ReleaseWndPtr(wndPtr);
Alexandre Julliard349a9531997-02-02 19:01:52 +00001353 tdb = (TDB*)GlobalLock16(htask);
Alexandre Julliard60ce85c1998-02-01 18:33:27 +00001354 if (!tdb || !tdb->thdb) return 0;
Alexandre Julliard8feb3bc1999-02-28 12:25:03 +00001355 if (process) *process = (DWORD)tdb->thdb->process->server_pid;
Marcus Meissner88e651d1999-03-13 18:20:26 +00001356 return (DWORD)tdb->thdb->server_tid;
Alexandre Julliard349a9531997-02-02 19:01:52 +00001357}
1358
Alexandre Julliardb817f4f1996-03-14 18:08:34 +00001359
1360/***********************************************************************
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001361 * SetMessageQueue16 (USER.266)
Alexandre Julliardb817f4f1996-03-14 18:08:34 +00001362 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001363BOOL16 WINAPI SetMessageQueue16( INT16 size )
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001364{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001365 return SetMessageQueue( size );
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001366}
1367
1368
1369/***********************************************************************
Alexandre Julliardc7c217b1998-04-13 12:21:30 +00001370 * SetMessageQueue32 (USER32.494)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001371 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001372BOOL WINAPI SetMessageQueue( INT size )
Alexandre Julliardb817f4f1996-03-14 18:08:34 +00001373{
Stephane Lussiera4c84451999-01-26 09:30:05 +00001374 /* now obsolete the message queue will be expanded dynamically
1375 as necessary */
Alexandre Julliardb817f4f1996-03-14 18:08:34 +00001376
Stephane Lussiera4c84451999-01-26 09:30:05 +00001377 /* access the queue to create it if it's not existing */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001378 GetFastQueue16();
Alexandre Julliard2ace16a1996-04-28 15:09:19 +00001379
Alexandre Julliardb817f4f1996-03-14 18:08:34 +00001380 return TRUE;
1381}
1382
Ulrich Weigand89b93bf1998-12-24 15:15:00 +00001383/***********************************************************************
1384 * InitThreadInput (USER.409)
1385 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001386HQUEUE16 WINAPI InitThreadInput16( WORD unknown, WORD flags )
Ulrich Weigand89b93bf1998-12-24 15:15:00 +00001387{
Stephane Lussiera4c84451999-01-26 09:30:05 +00001388 HQUEUE16 hQueue;
1389 MESSAGEQUEUE *queuePtr;
1390
1391 THDB *thdb = THREAD_Current();
1392
1393 if (!thdb)
1394 return 0;
1395
1396 hQueue = thdb->teb.queue;
1397
Alexandre Julliard638f1691999-01-17 16:32:32 +00001398 if ( !hQueue )
1399 {
Stephane Lussiera4c84451999-01-26 09:30:05 +00001400 /* Create thread message queue */
Noel Borthwickb4278561999-02-05 10:37:53 +00001401 if( !(hQueue = QUEUE_CreateMsgQueue( TRUE )))
Stephane Lussiera4c84451999-01-26 09:30:05 +00001402 {
1403 WARN(msg, "failed!\n");
1404 return FALSE;
1405 }
1406
1407 /* Link new queue into list */
Stephane Lussier1c4786f1999-01-28 10:54:11 +00001408 queuePtr = (MESSAGEQUEUE *)QUEUE_Lock( hQueue );
Stephane Lussiera4c84451999-01-26 09:30:05 +00001409 queuePtr->thdb = THREAD_Current();
1410
Alexandre Julliard34bf8151999-03-21 08:36:55 +00001411 HeapLock( SystemHeap ); /* FIXME: a bit overkill */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001412 SetThreadQueue16( 0, hQueue );
Stephane Lussiera4c84451999-01-26 09:30:05 +00001413 thdb->teb.queue = hQueue;
1414
1415 queuePtr->next = hFirstQueue;
1416 hFirstQueue = hQueue;
Alexandre Julliard34bf8151999-03-21 08:36:55 +00001417 HeapUnlock( SystemHeap );
Stephane Lussier1c4786f1999-01-28 10:54:11 +00001418
1419 QUEUE_Unlock( queuePtr );
Alexandre Julliard638f1691999-01-17 16:32:32 +00001420 }
Ulrich Weigand89b93bf1998-12-24 15:15:00 +00001421
Ulrich Weigand89b93bf1998-12-24 15:15:00 +00001422 return hQueue;
1423}
Alexandre Julliardb817f4f1996-03-14 18:08:34 +00001424
1425/***********************************************************************
Alexandre Julliard21979011997-03-05 08:22:35 +00001426 * GetQueueStatus16 (USER.334)
Alexandre Julliardb817f4f1996-03-14 18:08:34 +00001427 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001428DWORD WINAPI GetQueueStatus16( UINT16 flags )
Alexandre Julliardb817f4f1996-03-14 18:08:34 +00001429{
1430 MESSAGEQUEUE *queue;
1431 DWORD ret;
1432
Alexandre Julliarda3960291999-02-26 11:11:13 +00001433 if (!(queue = (MESSAGEQUEUE *)QUEUE_Lock( GetFastQueue16() ))) return 0;
Alexandre Julliardef702d81996-05-28 18:54:58 +00001434 ret = MAKELONG( queue->changeBits, queue->wakeBits );
1435 queue->changeBits = 0;
Stephane Lussier1c4786f1999-01-28 10:54:11 +00001436 QUEUE_Unlock( queue );
1437
Alexandre Julliardb817f4f1996-03-14 18:08:34 +00001438 return ret & MAKELONG( flags, flags );
1439}
1440
Alexandre Julliarde658d821997-11-30 17:45:40 +00001441/***********************************************************************
1442 * GetQueueStatus32 (USER32.283)
1443 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001444DWORD WINAPI GetQueueStatus( UINT flags )
Alexandre Julliarde658d821997-11-30 17:45:40 +00001445{
1446 MESSAGEQUEUE *queue;
1447 DWORD ret;
1448
Alexandre Julliarda3960291999-02-26 11:11:13 +00001449 if (!(queue = (MESSAGEQUEUE *)QUEUE_Lock( GetFastQueue16() ))) return 0;
Alexandre Julliarde658d821997-11-30 17:45:40 +00001450 ret = MAKELONG( queue->changeBits, queue->wakeBits );
1451 queue->changeBits = 0;
Stephane Lussier1c4786f1999-01-28 10:54:11 +00001452 QUEUE_Unlock( queue );
1453
Alexandre Julliarde658d821997-11-30 17:45:40 +00001454 return ret & MAKELONG( flags, flags );
1455}
1456
Alexandre Julliardb817f4f1996-03-14 18:08:34 +00001457
1458/***********************************************************************
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001459 * GetInputState16 (USER.335)
Alexandre Julliardb817f4f1996-03-14 18:08:34 +00001460 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001461BOOL16 WINAPI GetInputState16(void)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001462{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001463 return GetInputState();
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001464}
1465
Alexandre Julliard54c27111998-03-29 19:44:57 +00001466/***********************************************************************
1467 * WaitForInputIdle (USER32.577)
1468 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001469DWORD WINAPI WaitForInputIdle (HANDLE hProcess, DWORD dwTimeOut)
Alexandre Julliard54c27111998-03-29 19:44:57 +00001470{
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00001471 FIXME (msg, "(hProcess=%d, dwTimeOut=%ld): stub\n", hProcess, dwTimeOut);
Alexandre Julliard46ea8b31998-05-03 19:01:20 +00001472
Alexandre Julliard54c27111998-03-29 19:44:57 +00001473 return WAIT_TIMEOUT;
1474}
1475
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001476
1477/***********************************************************************
Alexandre Julliardc7c217b1998-04-13 12:21:30 +00001478 * GetInputState32 (USER32.244)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001479 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001480BOOL WINAPI GetInputState(void)
Alexandre Julliardb817f4f1996-03-14 18:08:34 +00001481{
1482 MESSAGEQUEUE *queue;
Alexandre Julliarda3960291999-02-26 11:11:13 +00001483 BOOL ret;
Alexandre Julliardb817f4f1996-03-14 18:08:34 +00001484
Alexandre Julliarda3960291999-02-26 11:11:13 +00001485 if (!(queue = (MESSAGEQUEUE *)QUEUE_Lock( GetFastQueue16() )))
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001486 return FALSE;
Stephane Lussier1c4786f1999-01-28 10:54:11 +00001487 ret = queue->wakeBits & (QS_KEY | QS_MOUSEBUTTON);
1488 QUEUE_Unlock( queue );
1489
1490 return ret;
Alexandre Julliardb817f4f1996-03-14 18:08:34 +00001491}
1492
Ulrich Weigand89b93bf1998-12-24 15:15:00 +00001493/***********************************************************************
1494 * UserYield (USER.332)
1495 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001496void WINAPI UserYield16(void)
Ulrich Weigand89b93bf1998-12-24 15:15:00 +00001497{
Ulrich Weigandda5779e1999-03-27 16:10:52 +00001498 MESSAGEQUEUE *queue;
Ulrich Weigand89b93bf1998-12-24 15:15:00 +00001499
1500 /* Handle sent messages */
Ulrich Weigandda5779e1999-03-27 16:10:52 +00001501 queue = (MESSAGEQUEUE *)QUEUE_Lock( GetFastQueue16() );
1502
Ulrich Weigand89b93bf1998-12-24 15:15:00 +00001503 while (queue && (queue->wakeBits & QS_SENDMESSAGE))
1504 QUEUE_ReceiveMessage( queue );
1505
Stephane Lussier1c4786f1999-01-28 10:54:11 +00001506 QUEUE_Unlock( queue );
1507
Ulrich Weigandda5779e1999-03-27 16:10:52 +00001508 /* Yield */
1509 if ( THREAD_IsWin16( THREAD_Current() ) )
1510 OldYield16();
1511 else
1512 {
Eric Pouech7f14c081999-04-01 09:58:53 +00001513 DWORD count;
1514
1515 ReleaseThunkLock(&count);
1516 RestoreThunkLock(count);
Ulrich Weigandda5779e1999-03-27 16:10:52 +00001517 }
Ulrich Weigand89b93bf1998-12-24 15:15:00 +00001518
Ulrich Weigandda5779e1999-03-27 16:10:52 +00001519 /* Handle sent messages again */
1520 queue = (MESSAGEQUEUE *)QUEUE_Lock( GetFastQueue16() );
1521
Ulrich Weigand89b93bf1998-12-24 15:15:00 +00001522 while (queue && (queue->wakeBits & QS_SENDMESSAGE))
1523 QUEUE_ReceiveMessage( queue );
Stephane Lussier1c4786f1999-01-28 10:54:11 +00001524
1525 QUEUE_Unlock( queue );
Ulrich Weigand89b93bf1998-12-24 15:15:00 +00001526}
Alexandre Julliardb817f4f1996-03-14 18:08:34 +00001527
1528/***********************************************************************
Alexandre Julliardc7c217b1998-04-13 12:21:30 +00001529 * GetMessagePos (USER.119) (USER32.272)
Douglas Ridgwayefaa5731998-10-25 09:20:30 +00001530 *
1531 * The GetMessagePos() function returns a long value representing a
1532 * cursor position, in screen coordinates, when the last message
1533 * retrieved by the GetMessage() function occurs. The x-coordinate is
1534 * in the low-order word of the return value, the y-coordinate is in
1535 * the high-order word. The application can use the MAKEPOINT()
1536 * macro to obtain a POINT structure from the return value.
1537 *
1538 * For the current cursor position, use GetCursorPos().
1539 *
1540 * RETURNS
1541 *
1542 * Cursor position of last message on success, zero on failure.
1543 *
1544 * CONFORMANCE
1545 *
1546 * ECMA-234, Win32
1547 *
Alexandre Julliardb817f4f1996-03-14 18:08:34 +00001548 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001549DWORD WINAPI GetMessagePos(void)
Alexandre Julliardb817f4f1996-03-14 18:08:34 +00001550{
1551 MESSAGEQUEUE *queue;
Stephane Lussier1c4786f1999-01-28 10:54:11 +00001552 DWORD ret;
Alexandre Julliardb817f4f1996-03-14 18:08:34 +00001553
Alexandre Julliarda3960291999-02-26 11:11:13 +00001554 if (!(queue = (MESSAGEQUEUE *)QUEUE_Lock( GetFastQueue16() ))) return 0;
Stephane Lussier1c4786f1999-01-28 10:54:11 +00001555 ret = queue->GetMessagePosVal;
1556 QUEUE_Unlock( queue );
1557
1558 return ret;
Alexandre Julliardb817f4f1996-03-14 18:08:34 +00001559}
1560
1561
1562/***********************************************************************
Alexandre Julliardc7c217b1998-04-13 12:21:30 +00001563 * GetMessageTime (USER.120) (USER32.273)
Douglas Ridgwayefaa5731998-10-25 09:20:30 +00001564 *
1565 * GetMessageTime() returns the message time for the last message
1566 * retrieved by the function. The time is measured in milliseconds with
1567 * the same offset as GetTickCount().
1568 *
1569 * Since the tick count wraps, this is only useful for moderately short
1570 * relative time comparisons.
1571 *
1572 * RETURNS
1573 *
1574 * Time of last message on success, zero on failure.
1575 *
1576 * CONFORMANCE
1577 *
1578 * ECMA-234, Win32
1579 *
Alexandre Julliardb817f4f1996-03-14 18:08:34 +00001580 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001581LONG WINAPI GetMessageTime(void)
Alexandre Julliardb817f4f1996-03-14 18:08:34 +00001582{
1583 MESSAGEQUEUE *queue;
Stephane Lussier1c4786f1999-01-28 10:54:11 +00001584 LONG ret;
Alexandre Julliardb817f4f1996-03-14 18:08:34 +00001585
Alexandre Julliarda3960291999-02-26 11:11:13 +00001586 if (!(queue = (MESSAGEQUEUE *)QUEUE_Lock( GetFastQueue16() ))) return 0;
Stephane Lussier1c4786f1999-01-28 10:54:11 +00001587 ret = queue->GetMessageTimeVal;
1588 QUEUE_Unlock( queue );
1589
1590 return ret;
Alexandre Julliardb817f4f1996-03-14 18:08:34 +00001591}
1592
1593
1594/***********************************************************************
Alexandre Julliardc7c217b1998-04-13 12:21:30 +00001595 * GetMessageExtraInfo (USER.288) (USER32.271)
Alexandre Julliardb817f4f1996-03-14 18:08:34 +00001596 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001597LONG WINAPI GetMessageExtraInfo(void)
Alexandre Julliardb817f4f1996-03-14 18:08:34 +00001598{
1599 MESSAGEQUEUE *queue;
Stephane Lussier1c4786f1999-01-28 10:54:11 +00001600 LONG ret;
Alexandre Julliardb817f4f1996-03-14 18:08:34 +00001601
Alexandre Julliarda3960291999-02-26 11:11:13 +00001602 if (!(queue = (MESSAGEQUEUE *)QUEUE_Lock( GetFastQueue16() ))) return 0;
Stephane Lussier1c4786f1999-01-28 10:54:11 +00001603 ret = queue->GetMessageExtraInfoVal;
1604 QUEUE_Unlock( queue );
1605
1606 return ret;
Alexandre Julliardb817f4f1996-03-14 18:08:34 +00001607}