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