Rewrote hook support to store the hook chain in the server.
[wine/wine-kai.git] / windows / queue.c
blob250b4ba97b8cd0c15531e62c186d5d697ddce638
1 /*
2 * Message queues related functions
4 * Copyright 1993, 1994 Alexandre Julliard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #include <string.h>
22 #include <signal.h>
23 #include <assert.h>
24 #include "windef.h"
25 #include "wingdi.h"
26 #include "winerror.h"
27 #include "wine/winbase16.h"
28 #include "wine/winuser16.h"
29 #include "queue.h"
30 #include "win.h"
31 #include "user.h"
32 #include "thread.h"
33 #include "wine/debug.h"
34 #include "wine/server.h"
35 #include "spy.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(msg);
40 /***********************************************************************
41 * QUEUE_Lock
43 * Function for getting a 32 bit pointer on queue structure. For thread
44 * safeness programmers should use this function instead of GlobalLock to
45 * retrieve a pointer on the structure. QUEUE_Unlock should also be called
46 * when access to the queue structure is not required anymore.
48 MESSAGEQUEUE *QUEUE_Lock( HQUEUE16 hQueue )
50 MESSAGEQUEUE *queue;
52 HeapLock( GetProcessHeap() ); /* FIXME: a bit overkill */
53 queue = GlobalLock16( hQueue );
54 if ( !queue || (queue->magic != QUEUE_MAGIC) )
56 HeapUnlock( GetProcessHeap() );
57 return NULL;
60 queue->lockCount++;
61 HeapUnlock( GetProcessHeap() );
62 return queue;
66 /***********************************************************************
67 * QUEUE_Current
69 * Get the current thread queue, creating it if required.
70 * QUEUE_Unlock is not needed since the queue can only be deleted by
71 * the current thread anyway.
73 MESSAGEQUEUE *QUEUE_Current(void)
75 MESSAGEQUEUE *queue;
76 HQUEUE16 hQueue;
78 if (!(hQueue = GetThreadQueue16(0)))
80 if (!(hQueue = InitThreadInput16( 0, 0 ))) return NULL;
83 if ((queue = GlobalLock16( hQueue )))
85 if (queue->magic != QUEUE_MAGIC) queue = NULL;
87 return queue;
91 /***********************************************************************
92 * QUEUE_Unlock
94 * Use with QUEUE_Lock to get a thread safe access to message queue
95 * structure
97 void QUEUE_Unlock( MESSAGEQUEUE *queue )
99 if (queue)
101 HeapLock( GetProcessHeap() ); /* FIXME: a bit overkill */
103 if ( --queue->lockCount == 0 )
105 if (queue->server_queue)
106 CloseHandle( queue->server_queue );
107 GlobalFree16( queue->self );
110 HeapUnlock( GetProcessHeap() );
115 /***********************************************************************
116 * QUEUE_CreateMsgQueue
118 * Creates a message queue. Doesn't link it into queue list!
120 static HQUEUE16 QUEUE_CreateMsgQueue( BOOL16 bCreatePerQData )
122 HQUEUE16 hQueue;
123 HANDLE handle;
124 MESSAGEQUEUE * msgQueue;
126 TRACE_(msg)("(): Creating message queue...\n");
128 if (!(hQueue = GlobalAlloc16( GMEM_FIXED | GMEM_ZEROINIT,
129 sizeof(MESSAGEQUEUE) )))
130 return 0;
132 msgQueue = (MESSAGEQUEUE *) GlobalLock16( hQueue );
133 if ( !msgQueue )
134 return 0;
136 if (bCreatePerQData)
138 SERVER_START_REQ( get_msg_queue )
140 wine_server_call_err( req );
141 handle = reply->handle;
143 SERVER_END_REQ;
144 if (!handle)
146 ERR_(msg)("Cannot get thread queue");
147 GlobalFree16( hQueue );
148 return 0;
150 msgQueue->server_queue = handle;
153 msgQueue->self = hQueue;
154 msgQueue->lockCount = 1;
155 msgQueue->magic = QUEUE_MAGIC;
156 return hQueue;
160 /***********************************************************************
161 * QUEUE_DeleteMsgQueue
163 * Unlinks and deletes a message queue.
165 * Note: We need to mask asynchronous events to make sure PostMessage works
166 * even in the signal handler.
168 void QUEUE_DeleteMsgQueue(void)
170 HQUEUE16 hQueue = GetThreadQueue16(0);
171 MESSAGEQUEUE * msgQueue;
173 if (!hQueue) return; /* thread doesn't have a queue */
175 TRACE("(): Deleting message queue %04x\n", hQueue);
177 if (!(msgQueue = QUEUE_Lock(hQueue)))
179 ERR("invalid thread queue\n");
180 return;
183 msgQueue->magic = 0;
184 msgQueue->self = 0;
185 SetThreadQueue16( 0, 0 );
187 /* free up resource used by MESSAGEQUEUE structure */
188 msgQueue->lockCount--;
189 QUEUE_Unlock( msgQueue );
193 /***********************************************************************
194 * InitThreadInput (USER.409)
196 HQUEUE16 WINAPI InitThreadInput16( WORD unknown, WORD flags )
198 MESSAGEQUEUE *queuePtr;
199 HQUEUE16 hQueue = NtCurrentTeb()->queue;
201 if ( !hQueue )
203 /* Create thread message queue */
204 if( !(hQueue = QUEUE_CreateMsgQueue( TRUE )))
206 ERR_(msg)("failed!\n");
207 return FALSE;
210 /* Link new queue into list */
211 queuePtr = QUEUE_Lock( hQueue );
213 HeapLock( GetProcessHeap() ); /* FIXME: a bit overkill */
214 SetThreadQueue16( 0, hQueue );
215 NtCurrentTeb()->queue = hQueue;
216 HeapUnlock( GetProcessHeap() );
218 QUEUE_Unlock( queuePtr );
221 return hQueue;
224 /***********************************************************************
225 * GetQueueStatus (USER32.@)
227 DWORD WINAPI GetQueueStatus( UINT flags )
229 DWORD ret = 0;
231 SERVER_START_REQ( get_queue_status )
233 req->clear = 1;
234 wine_server_call( req );
235 ret = MAKELONG( reply->changed_bits & flags, reply->wake_bits & flags );
237 SERVER_END_REQ;
238 return ret;
242 /***********************************************************************
243 * GetInputState (USER32.@)
245 BOOL WINAPI GetInputState(void)
247 DWORD ret = 0;
249 SERVER_START_REQ( get_queue_status )
251 req->clear = 0;
252 wine_server_call( req );
253 ret = reply->wake_bits & (QS_KEY | QS_MOUSEBUTTON);
255 SERVER_END_REQ;
256 return ret;
259 /***********************************************************************
260 * GetMessagePos (USER.119)
261 * GetMessagePos (USER32.@)
263 * The GetMessagePos() function returns a long value representing a
264 * cursor position, in screen coordinates, when the last message
265 * retrieved by the GetMessage() function occurs. The x-coordinate is
266 * in the low-order word of the return value, the y-coordinate is in
267 * the high-order word. The application can use the MAKEPOINT()
268 * macro to obtain a POINT structure from the return value.
270 * For the current cursor position, use GetCursorPos().
272 * RETURNS
274 * Cursor position of last message on success, zero on failure.
276 * CONFORMANCE
278 * ECMA-234, Win32
281 DWORD WINAPI GetMessagePos(void)
283 MESSAGEQUEUE *queue;
285 if (!(queue = QUEUE_Current())) return 0;
286 return queue->GetMessagePosVal;
290 /***********************************************************************
291 * GetMessageTime (USER.120)
292 * GetMessageTime (USER32.@)
294 * GetMessageTime() returns the message time for the last message
295 * retrieved by the function. The time is measured in milliseconds with
296 * the same offset as GetTickCount().
298 * Since the tick count wraps, this is only useful for moderately short
299 * relative time comparisons.
301 * RETURNS
303 * Time of last message on success, zero on failure.
305 * CONFORMANCE
307 * ECMA-234, Win32
310 LONG WINAPI GetMessageTime(void)
312 MESSAGEQUEUE *queue;
314 if (!(queue = QUEUE_Current())) return 0;
315 return queue->GetMessageTimeVal;
319 /***********************************************************************
320 * GetMessageExtraInfo (USER.288)
321 * GetMessageExtraInfo (USER32.@)
323 LONG WINAPI GetMessageExtraInfo(void)
325 MESSAGEQUEUE *queue;
327 if (!(queue = QUEUE_Current())) return 0;
328 return queue->GetMessageExtraInfoVal;