Rewrote hook support to store the hook chain in the server.
[wine] / dlls / user / msg16.c
1 /*
2  * 16-bit messaging support
3  *
4  * Copyright 2001 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 "wine/winuser16.h"
22 #include "wownt32.h"
23 #include "winerror.h"
24 #include "message.h"
25 #include "spy.h"
26 #include "thread.h"
27 #include "win.h"
28 #include "wine/debug.h"
29
30 WINE_DEFAULT_DEBUG_CHANNEL(msg);
31
32 DWORD USER16_AlertableWait = 0;
33
34 /***********************************************************************
35  *              SendMessage  (USER.111)
36  */
37 LRESULT WINAPI SendMessage16( HWND16 hwnd16, UINT16 msg, WPARAM16 wparam, LPARAM lparam )
38 {
39     LRESULT result;
40     UINT msg32;
41     WPARAM wparam32;
42     HWND hwnd = WIN_Handle32( hwnd16 );
43
44     if (hwnd != HWND_BROADCAST && WIN_IsCurrentThread(hwnd))
45     {
46         /* call 16-bit window proc directly */
47         WNDPROC16 winproc;
48
49         /* first the WH_CALLWNDPROC hook */
50         if (HOOK_IsHooked( WH_CALLWNDPROC ))
51         {
52             LPARAM lparam32 = lparam;
53
54             if (WINPROC_MapMsg16To32A( hwnd, msg, wparam, &msg32, &wparam32, &lparam32 ) != -1)
55             {
56                 CWPSTRUCT cwp;
57
58                 cwp.hwnd    = hwnd;
59                 cwp.message = msg32;
60                 cwp.wParam  = wparam32;
61                 cwp.lParam  = lparam32;
62                 HOOK_CallHooks( WH_CALLWNDPROC, HC_ACTION, 1, (LPARAM)&cwp, FALSE );
63                 WINPROC_UnmapMsg16To32A( hwnd, msg32, wparam32, lparam32, 0 );
64                 /* FIXME: should reflect changes back into the message we send */
65             }
66         }
67
68         if (!(winproc = (WNDPROC16)GetWindowLong16( hwnd16, GWL_WNDPROC ))) return 0;
69
70         SPY_EnterMessage( SPY_SENDMESSAGE16, hwnd, msg, wparam, lparam );
71         result = CallWindowProc16( (WNDPROC16)winproc, hwnd16, msg, wparam, lparam );
72         SPY_ExitMessage( SPY_RESULT_OK16, hwnd, msg, result, wparam, lparam );
73     }
74     else  /* map to 32-bit unicode for inter-thread/process message */
75     {
76         if (WINPROC_MapMsg16To32W( hwnd, msg, wparam, &msg32, &wparam32, &lparam ) == -1)
77             return 0;
78         result = WINPROC_UnmapMsg16To32W( hwnd, msg32, wparam32, lparam,
79                                           SendMessageW( hwnd, msg32, wparam32, lparam ) );
80     }
81     return result;
82 }
83
84
85 /***********************************************************************
86  *              PostMessage  (USER.110)
87  */
88 BOOL16 WINAPI PostMessage16( HWND16 hwnd16, UINT16 msg, WPARAM16 wparam, LPARAM lparam )
89 {
90     WPARAM wparam32;
91     UINT msg32;
92     HWND hwnd = WIN_Handle32( hwnd16 );
93
94     switch (WINPROC_MapMsg16To32W( hwnd, msg, wparam, &msg32, &wparam32, &lparam ))
95     {
96     case 0:
97         return PostMessageW( hwnd, msg32, wparam32, lparam );
98     case 1:
99         ERR( "16-bit message 0x%04x contains pointer, cannot post\n", msg );
100         return FALSE;
101     default:
102         return FALSE;
103     }
104 }
105
106
107 /***********************************************************************
108  *              PostAppMessage (USER.116)
109  */
110 BOOL16 WINAPI PostAppMessage16( HTASK16 hTask, UINT16 msg, WPARAM16 wparam, LPARAM lparam )
111 {
112     WPARAM wparam32;
113     UINT msg32;
114     DWORD tid = HTASK_32( hTask );
115     if (!tid) return FALSE;
116
117     switch (WINPROC_MapMsg16To32W( 0, msg, wparam, &msg32, &wparam32, &lparam ))
118     {
119     case 0:
120         return PostThreadMessageW( tid, msg32, wparam32, lparam );
121     case 1:
122         ERR( "16-bit message %x contains pointer, cannot post\n", msg );
123         return FALSE;
124     default:
125         return FALSE;
126     }
127 }
128
129
130 /***********************************************************************
131  *              InSendMessage  (USER.192)
132  */
133 BOOL16 WINAPI InSendMessage16(void)
134 {
135     return InSendMessage();
136 }
137
138
139 /***********************************************************************
140  *              ReplyMessage  (USER.115)
141  */
142 void WINAPI ReplyMessage16( LRESULT result )
143 {
144     ReplyMessage( result );
145 }
146
147
148 /***********************************************************************
149  *              PeekMessage32 (USER.819)
150  */
151 BOOL16 WINAPI PeekMessage32_16( MSG32_16 *msg16, HWND16 hwnd16,
152                                 UINT16 first, UINT16 last, UINT16 flags,
153                                 BOOL16 wHaveParamHigh )
154 {
155     MSG msg;
156     HWND hwnd = WIN_Handle32( hwnd16 );
157
158     if(USER16_AlertableWait)
159         MsgWaitForMultipleObjectsEx( 0, NULL, 1, 0, MWMO_ALERTABLE );
160     if (!PeekMessageW( &msg, hwnd, first, last, flags )) return FALSE;
161
162     msg16->msg.hwnd    = HWND_16( msg.hwnd );
163     msg16->msg.lParam  = msg.lParam;
164     msg16->msg.time    = msg.time;
165     msg16->msg.pt.x    = (INT16)msg.pt.x;
166     msg16->msg.pt.y    = (INT16)msg.pt.y;
167     if (wHaveParamHigh) msg16->wParamHigh = HIWORD(msg.wParam);
168
169     return (WINPROC_MapMsg32WTo16( msg.hwnd, msg.message, msg.wParam,
170                                    &msg16->msg.message, &msg16->msg.wParam,
171                                    &msg16->msg.lParam ) != -1);
172 }
173
174
175 /***********************************************************************
176  *              PeekMessage  (USER.109)
177  */
178 BOOL16 WINAPI PeekMessage16( MSG16 *msg, HWND16 hwnd,
179                              UINT16 first, UINT16 last, UINT16 flags )
180 {
181     return PeekMessage32_16( (MSG32_16 *)msg, hwnd, first, last, flags, FALSE );
182 }
183
184
185 /***********************************************************************
186  *              GetMessage32  (USER.820)
187  */
188 BOOL16 WINAPI GetMessage32_16( MSG32_16 *msg16, HWND16 hwnd16, UINT16 first,
189                                UINT16 last, BOOL16 wHaveParamHigh )
190 {
191     MSG msg;
192     HWND hwnd = WIN_Handle32( hwnd16 );
193
194     do
195     {
196         if(USER16_AlertableWait)
197             MsgWaitForMultipleObjectsEx( 0, NULL, INFINITE, 0, MWMO_ALERTABLE );
198         GetMessageW( &msg, hwnd, first, last );
199         msg16->msg.hwnd    = HWND_16( msg.hwnd );
200         msg16->msg.lParam  = msg.lParam;
201         msg16->msg.time    = msg.time;
202         msg16->msg.pt.x    = (INT16)msg.pt.x;
203         msg16->msg.pt.y    = (INT16)msg.pt.y;
204         if (wHaveParamHigh) msg16->wParamHigh = HIWORD(msg.wParam);
205     }
206     while (WINPROC_MapMsg32WTo16( msg.hwnd, msg.message, msg.wParam,
207                                   &msg16->msg.message, &msg16->msg.wParam,
208                                   &msg16->msg.lParam ) == -1);
209
210     TRACE( "message %04x, hwnd %04x, filter(%04x - %04x)\n",
211            msg16->msg.message, hwnd, first, last );
212
213     return msg16->msg.message != WM_QUIT;
214 }
215
216
217 /***********************************************************************
218  *              GetMessage  (USER.108)
219  */
220 BOOL16 WINAPI GetMessage16( MSG16 *msg, HWND16 hwnd, UINT16 first, UINT16 last )
221 {
222     return GetMessage32_16( (MSG32_16 *)msg, hwnd, first, last, FALSE );
223 }
224
225
226 /***********************************************************************
227  *              TranslateMessage32 (USER.821)
228  */
229 BOOL16 WINAPI TranslateMessage32_16( const MSG32_16 *msg, BOOL16 wHaveParamHigh )
230 {
231     MSG msg32;
232
233     msg32.hwnd    = WIN_Handle32( msg->msg.hwnd );
234     msg32.message = msg->msg.message;
235     msg32.wParam  = MAKEWPARAM( msg->msg.wParam, wHaveParamHigh ? msg->wParamHigh : 0 );
236     msg32.lParam  = msg->msg.lParam;
237     return TranslateMessage( &msg32 );
238 }
239
240
241 /***********************************************************************
242  *              TranslateMessage (USER.113)
243  */
244 BOOL16 WINAPI TranslateMessage16( const MSG16 *msg )
245 {
246     return TranslateMessage32_16( (MSG32_16 *)msg, FALSE );
247 }
248
249
250 /***********************************************************************
251  *              DispatchMessage (USER.114)
252  */
253 LONG WINAPI DispatchMessage16( const MSG16* msg )
254 {
255     WND * wndPtr;
256     WNDPROC16 winproc;
257     LONG retval;
258     int painting;
259     HWND hwnd = WIN_Handle32( msg->hwnd );
260
261       /* Process timer messages */
262     if ((msg->message == WM_TIMER) || (msg->message == WM_SYSTIMER))
263     {
264         if (msg->lParam)
265         {
266             /* before calling window proc, verify whether timer is still valid;
267                there's a slim chance that the application kills the timer
268                between GetMessage and DispatchMessage API calls */
269             if (!TIMER_IsTimerValid(hwnd, (UINT) msg->wParam, (HWINDOWPROC) msg->lParam))
270                 return 0; /* invalid winproc */
271
272             return CallWindowProc16( (WNDPROC16)msg->lParam, msg->hwnd,
273                                      msg->message, msg->wParam, GetTickCount() );
274         }
275     }
276
277     if (!(wndPtr = WIN_GetPtr( hwnd )))
278     {
279         if (msg->hwnd) SetLastError( ERROR_INVALID_WINDOW_HANDLE );
280         return 0;
281     }
282     if (wndPtr == WND_OTHER_PROCESS)
283     {
284         if (IsWindow( hwnd ))
285             ERR( "cannot dispatch msg to other process window %x\n", hwnd );
286         SetLastError( ERROR_INVALID_WINDOW_HANDLE );
287         return 0;
288     }
289
290     if (!(winproc = (WNDPROC16)wndPtr->winproc))
291     {
292         WIN_ReleasePtr( wndPtr );
293         return 0;
294     }
295     painting = (msg->message == WM_PAINT);
296     if (painting) wndPtr->flags |= WIN_NEEDS_BEGINPAINT;
297     WIN_ReleasePtr( wndPtr );
298
299     SPY_EnterMessage( SPY_DISPATCHMESSAGE16, hwnd, msg->message, msg->wParam, msg->lParam );
300     retval = CallWindowProc16( winproc, msg->hwnd, msg->message, msg->wParam, msg->lParam );
301     SPY_ExitMessage( SPY_RESULT_OK16, hwnd, msg->message, retval, msg->wParam, msg->lParam );
302
303     if (painting && (wndPtr = WIN_GetPtr( hwnd )) && (wndPtr != WND_OTHER_PROCESS))
304     {
305         BOOL validate = ((wndPtr->flags & WIN_NEEDS_BEGINPAINT) && wndPtr->hrgnUpdate);
306         wndPtr->flags &= ~WIN_NEEDS_BEGINPAINT;
307         WIN_ReleasePtr( wndPtr );
308         if (validate)
309         {
310             ERR( "BeginPaint not called on WM_PAINT for hwnd %x!\n", hwnd );
311             /* Validate the update region to avoid infinite WM_PAINT loop */
312             RedrawWindow( hwnd, NULL, 0,
313                           RDW_NOFRAME | RDW_VALIDATE | RDW_NOCHILDREN | RDW_NOINTERNALPAINT );
314         }
315     }
316     return retval;
317 }
318
319
320 /***********************************************************************
321  *              DispatchMessage32 (USER.822)
322  */
323 LONG WINAPI DispatchMessage32_16( const MSG32_16 *msg16, BOOL16 wHaveParamHigh )
324 {
325     if (wHaveParamHigh == FALSE)
326         return DispatchMessage16( &msg16->msg );
327     else
328     {
329         MSG msg;
330
331         msg.hwnd    = WIN_Handle32( msg16->msg.hwnd );
332         msg.message = msg16->msg.message;
333         msg.wParam  = MAKEWPARAM( msg16->msg.wParam, msg16->wParamHigh );
334         msg.lParam  = msg16->msg.lParam;
335         msg.time    = msg16->msg.time;
336         msg.pt.x    = msg16->msg.pt.x;
337         msg.pt.y    = msg16->msg.pt.y;
338         return DispatchMessageA( &msg );
339     }
340 }
341
342
343 /***********************************************************************
344  *              IsDialogMessage (USER.90)
345  */
346 BOOL16 WINAPI IsDialogMessage16( HWND16 hwndDlg, MSG16 *msg16 )
347 {
348     MSG msg;
349
350     switch(msg16->message)
351     {
352     case WM_KEYDOWN:
353     case WM_CHAR:
354     case WM_SYSCHAR:
355         msg.hwnd   = WIN_Handle32(msg16->hwnd);
356         msg.lParam = msg16->lParam;
357         WINPROC_MapMsg16To32W( msg.hwnd, msg16->message, msg16->wParam,
358                                &msg.message, &msg.wParam, &msg.lParam );
359         /* these messages don't need an unmap */
360         return IsDialogMessageW( WIN_Handle32(hwndDlg), &msg );
361     }
362     TranslateMessage16( msg16 );
363     DispatchMessage16( msg16 );
364     return TRUE;
365 }
366
367
368 /***********************************************************************
369  *              MsgWaitForMultipleObjects  (USER.640)
370  */
371 DWORD WINAPI MsgWaitForMultipleObjects16( DWORD count, CONST HANDLE *handles,
372                                           BOOL wait_all, DWORD timeout, DWORD mask )
373 {
374     return MsgWaitForMultipleObjectsEx( count, handles, timeout, mask,
375                                         wait_all ? MWMO_WAITALL : 0 );
376 }
377
378
379 /**********************************************************************
380  *              SetDoubleClickTime (USER.20)
381  */
382 void WINAPI SetDoubleClickTime16( UINT16 interval )
383 {
384     SetDoubleClickTime( interval );
385 }
386
387
388 /**********************************************************************
389  *              GetDoubleClickTime (USER.21)
390  */
391 UINT16 WINAPI GetDoubleClickTime16(void)
392 {
393     return GetDoubleClickTime();
394 }
395
396
397 /***********************************************************************
398  *              PostQuitMessage (USER.6)
399  */
400 void WINAPI PostQuitMessage16( INT16 exitCode )
401 {
402     PostQuitMessage( exitCode );
403 }
404
405
406 /***********************************************************************
407  *              SetMessageQueue (USER.266)
408  */
409 BOOL16 WINAPI SetMessageQueue16( INT16 size )
410 {
411     return SetMessageQueue( size );
412 }
413
414
415 /***********************************************************************
416  *              GetQueueStatus (USER.334)
417  */
418 DWORD WINAPI GetQueueStatus16( UINT16 flags )
419 {
420     return GetQueueStatus( flags );
421 }
422
423
424 /***********************************************************************
425  *              GetInputState (USER.335)
426  */
427 BOOL16 WINAPI GetInputState16(void)
428 {
429     return GetInputState();
430 }
431
432
433 /**********************************************************************
434  *           TranslateAccelerator      (USER.178)
435  */
436 INT16 WINAPI TranslateAccelerator16( HWND16 hwnd, HACCEL16 hAccel, LPMSG16 msg )
437 {
438     MSG msg32;
439
440     if (!msg) return 0;
441     msg32.message = msg->message;
442     /* msg32.hwnd not used */
443     msg32.wParam  = msg->wParam;
444     msg32.lParam  = msg->lParam;
445     return TranslateAccelerator( WIN_Handle32(hwnd), HACCEL_32(hAccel), &msg32 );
446 }
447
448
449 /**********************************************************************
450  *              TranslateMDISysAccel (USER.451)
451  */
452 BOOL16 WINAPI TranslateMDISysAccel16( HWND16 hwndClient, LPMSG16 msg )
453 {
454     if (msg->message == WM_KEYDOWN || msg->message == WM_SYSKEYDOWN)
455     {
456         MSG msg32;
457         msg32.hwnd    = WIN_Handle32(msg->hwnd);
458         msg32.message = msg->message;
459         msg32.wParam  = msg->wParam;
460         msg32.lParam  = msg->lParam;
461         /* MDICLIENTINFO is still the same for win32 and win16 ... */
462         return TranslateMDISysAccel( WIN_Handle32(hwndClient), &msg32 );
463     }
464     return 0;
465 }