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