SLOWORD and SHIWORD do not exist on Win32 (reported by Filip Navara).
[wine] / windows / queue.c
1 /*
2  * Message queues related functions
3  *
4  * Copyright 1993, 1994 Alexandre Julliard
5  *
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.
10  *
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.
15  *
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
19  */
20
21 #include <stdarg.h>
22 #include <string.h>
23 #include <signal.h>
24 #include <assert.h>
25 #include "windef.h"
26 #include "winbase.h"
27 #include "wingdi.h"
28 #include "winerror.h"
29 #include "wine/winbase16.h"
30 #include "wine/winuser16.h"
31 #include "message.h"
32 #include "win.h"
33 #include "user.h"
34 #include "thread.h"
35 #include "wine/debug.h"
36 #include "wine/server.h"
37
38 WINE_DEFAULT_DEBUG_CHANNEL(msg);
39
40
41 /***********************************************************************
42  *           QUEUE_CreateMsgQueue
43  *
44  * Creates a message queue. Doesn't link it into queue list!
45  */
46 static HQUEUE16 QUEUE_CreateMsgQueue(void)
47 {
48     HQUEUE16 hQueue;
49     HANDLE handle;
50     MESSAGEQUEUE * msgQueue;
51
52     TRACE_(msg)("(): Creating message queue...\n");
53
54     if (!(hQueue = GlobalAlloc16( GMEM_FIXED | GMEM_ZEROINIT,
55                                   sizeof(MESSAGEQUEUE) )))
56         return 0;
57
58     msgQueue = (MESSAGEQUEUE *) GlobalLock16( hQueue );
59     if ( !msgQueue )
60         return 0;
61
62     SERVER_START_REQ( get_msg_queue )
63     {
64         wine_server_call_err( req );
65         handle = reply->handle;
66     }
67     SERVER_END_REQ;
68     if (!handle)
69     {
70         ERR_(msg)("Cannot get thread queue");
71         GlobalFree16( hQueue );
72         return 0;
73     }
74     msgQueue->server_queue = handle;
75     msgQueue->self = hQueue;
76     return hQueue;
77 }
78
79
80 /***********************************************************************
81  *           QUEUE_Current
82  *
83  * Get the current thread queue, creating it if required.
84  * QUEUE_Unlock is not needed since the queue can only be deleted by
85  * the current thread anyway.
86  */
87 MESSAGEQUEUE *QUEUE_Current(void)
88 {
89     HQUEUE16 hQueue = NtCurrentTeb()->queue;
90
91     if (!hQueue)
92     {
93         if (!(hQueue = QUEUE_CreateMsgQueue())) return NULL;
94         SetThreadQueue16( 0, hQueue );
95     }
96
97     return GlobalLock16( hQueue );
98 }
99
100
101
102 /***********************************************************************
103  *           QUEUE_DeleteMsgQueue
104  *
105  * Delete a message queue.
106  */
107 void QUEUE_DeleteMsgQueue(void)
108 {
109     HQUEUE16 hQueue = NtCurrentTeb()->queue;
110     MESSAGEQUEUE * msgQueue;
111
112     if (!hQueue) return;  /* thread doesn't have a queue */
113
114     TRACE("(): Deleting message queue %04x\n", hQueue);
115
116     if (!(msgQueue = GlobalLock16( hQueue )))
117     {
118         ERR("invalid thread queue\n");
119         return;
120     }
121
122     SetThreadQueue16( 0, 0 );
123     CloseHandle( msgQueue->server_queue );
124     GlobalFree16( hQueue );
125 }
126
127
128 /***********************************************************************
129  *              InitThreadInput   (USER.409)
130  */
131 HQUEUE16 WINAPI InitThreadInput16( WORD unknown, WORD flags )
132 {
133     MESSAGEQUEUE *queue = QUEUE_Current();
134     return queue ? queue->self : 0;
135 }
136
137 /***********************************************************************
138  *              GetQueueStatus (USER32.@)
139  */
140 DWORD WINAPI GetQueueStatus( UINT flags )
141 {
142     DWORD ret = 0;
143
144     /* check for pending X events */
145     if (USER_Driver.pMsgWaitForMultipleObjectsEx)
146         USER_Driver.pMsgWaitForMultipleObjectsEx( 0, NULL, 0, 0, 0 );
147
148     SERVER_START_REQ( get_queue_status )
149     {
150         req->clear = 1;
151         wine_server_call( req );
152         ret = MAKELONG( reply->changed_bits & flags, reply->wake_bits & flags );
153     }
154     SERVER_END_REQ;
155     return ret;
156 }
157
158
159 /***********************************************************************
160  *              GetInputState   (USER32.@)
161  */
162 BOOL WINAPI GetInputState(void)
163 {
164     DWORD ret = 0;
165
166     /* check for pending X events */
167     if (USER_Driver.pMsgWaitForMultipleObjectsEx)
168         USER_Driver.pMsgWaitForMultipleObjectsEx( 0, NULL, 0, 0, 0 );
169
170     SERVER_START_REQ( get_queue_status )
171     {
172         req->clear = 0;
173         wine_server_call( req );
174         ret = reply->wake_bits & (QS_KEY | QS_MOUSEBUTTON);
175     }
176     SERVER_END_REQ;
177     return ret;
178 }
179
180 /***********************************************************************
181  *              GetMessagePos (USER.119)
182  *              GetMessagePos (USER32.@)
183  *
184  * The GetMessagePos() function returns a long value representing a
185  * cursor position, in screen coordinates, when the last message
186  * retrieved by the GetMessage() function occurs. The x-coordinate is
187  * in the low-order word of the return value, the y-coordinate is in
188  * the high-order word. The application can use the MAKEPOINT()
189  * macro to obtain a POINT structure from the return value.
190  *
191  * For the current cursor position, use GetCursorPos().
192  *
193  * RETURNS
194  *
195  * Cursor position of last message on success, zero on failure.
196  *
197  * CONFORMANCE
198  *
199  * ECMA-234, Win32
200  *
201  */
202 DWORD WINAPI GetMessagePos(void)
203 {
204     MESSAGEQUEUE *queue;
205
206     if (!(queue = QUEUE_Current())) return 0;
207     return queue->GetMessagePosVal;
208 }
209
210
211 /***********************************************************************
212  *              GetMessageTime (USER.120)
213  *              GetMessageTime (USER32.@)
214  *
215  * GetMessageTime() returns the message time for the last message
216  * retrieved by the function. The time is measured in milliseconds with
217  * the same offset as GetTickCount().
218  *
219  * Since the tick count wraps, this is only useful for moderately short
220  * relative time comparisons.
221  *
222  * RETURNS
223  *
224  * Time of last message on success, zero on failure.
225  *
226  * CONFORMANCE
227  *
228  * ECMA-234, Win32
229  *
230  */
231 LONG WINAPI GetMessageTime(void)
232 {
233     MESSAGEQUEUE *queue;
234
235     if (!(queue = QUEUE_Current())) return 0;
236     return queue->GetMessageTimeVal;
237 }
238
239
240 /***********************************************************************
241  *              GetMessageExtraInfo (USER.288)
242  *              GetMessageExtraInfo (USER32.@)
243  */
244 LPARAM WINAPI GetMessageExtraInfo(void)
245 {
246     MESSAGEQUEUE *queue;
247
248     if (!(queue = QUEUE_Current())) return 0;
249     return queue->GetMessageExtraInfoVal;
250 }
251
252
253 /***********************************************************************
254  *              SetMessageExtraInfo (USER32.@)
255  */
256 LPARAM WINAPI SetMessageExtraInfo(LPARAM lParam)
257 {
258     MESSAGEQUEUE *queue;
259     LONG old_value;
260
261     if (!(queue = QUEUE_Current())) return 0;
262     old_value = queue->GetMessageExtraInfoVal;
263     queue->GetMessageExtraInfoVal = lParam;
264     return old_value;
265 }