user: Correct buffer overflows in IME processing code.
[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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20
21 #include "wine/winuser16.h"
22 #include "wownt32.h"
23 #include "winerror.h"
24 #include "win.h"
25 #include "user_private.h"
26 #include "winproc.h"
27 #include "wine/debug.h"
28
29 WINE_DEFAULT_DEBUG_CHANNEL(msg);
30
31 DWORD USER16_AlertableWait = 0;
32
33 static LRESULT cwp_hook_callback( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp,
34                                   LRESULT *result, void *arg )
35 {
36     CWPSTRUCT cwp;
37
38     cwp.hwnd    = hwnd;
39     cwp.message = msg;
40     cwp.wParam  = wp;
41     cwp.lParam  = lp;
42     *result = 0;
43     return HOOK_CallHooks( WH_CALLWNDPROC, HC_ACTION, 1, (LPARAM)&cwp, FALSE );
44 }
45
46 static LRESULT send_message_callback( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp,
47                                       LRESULT *result, void *arg )
48 {
49     *result = SendMessageA( hwnd, msg, wp, lp );
50     return *result;
51 }
52
53 static LRESULT post_message_callback( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp,
54                                       LRESULT *result, void *arg )
55 {
56     *result = 0;
57     return PostMessageA( hwnd, msg, wp, lp );
58 }
59
60 static LRESULT post_thread_message_callback( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp,
61                                              LRESULT *result, void *arg )
62 {
63     DWORD_PTR tid = (DWORD_PTR)arg;
64     *result = 0;
65     return PostThreadMessageA( tid, msg, wp, lp );
66 }
67
68 static LRESULT get_message_callback( HWND16 hwnd, UINT16 msg, WPARAM16 wp, LPARAM lp,
69                                      LRESULT *result, void *arg )
70 {
71     MSG16 *msg16 = arg;
72
73     msg16->hwnd    = hwnd;
74     msg16->message = msg;
75     msg16->wParam  = wp;
76     msg16->lParam  = lp;
77     *result = 0;
78     return 0;
79 }
80
81
82 /***********************************************************************
83  *              SendMessage  (USER.111)
84  */
85 LRESULT WINAPI SendMessage16( HWND16 hwnd16, UINT16 msg, WPARAM16 wparam, LPARAM lparam )
86 {
87     LRESULT result;
88     HWND hwnd = WIN_Handle32( hwnd16 );
89
90     if (hwnd != HWND_BROADCAST && WIN_IsCurrentThread(hwnd))
91     {
92         /* call 16-bit window proc directly */
93         WNDPROC16 winproc;
94
95         /* first the WH_CALLWNDPROC hook */
96         if (HOOK_IsHooked( WH_CALLWNDPROC ))
97             WINPROC_CallProc16To32A( cwp_hook_callback, hwnd16, msg, wparam, lparam, &result, NULL );
98
99         if (!(winproc = (WNDPROC16)GetWindowLong16( hwnd16, GWLP_WNDPROC ))) return 0;
100
101         SPY_EnterMessage( SPY_SENDMESSAGE16, hwnd, msg, wparam, lparam );
102         result = CallWindowProc16( winproc, hwnd16, msg, wparam, lparam );
103         SPY_ExitMessage( SPY_RESULT_OK16, hwnd, msg, result, wparam, lparam );
104     }
105     else  /* map to 32-bit unicode for inter-thread/process message */
106     {
107         WINPROC_CallProc16To32A( send_message_callback, hwnd16, msg, wparam, lparam, &result, NULL );
108     }
109     return result;
110 }
111
112
113 /***********************************************************************
114  *              PostMessage  (USER.110)
115  */
116 BOOL16 WINAPI PostMessage16( HWND16 hwnd, UINT16 msg, WPARAM16 wparam, LPARAM lparam )
117 {
118     LRESULT unused;
119     return WINPROC_CallProc16To32A( post_message_callback, hwnd, msg, wparam, lparam, &unused, NULL );
120 }
121
122
123 /***********************************************************************
124  *              PostAppMessage (USER.116)
125  */
126 BOOL16 WINAPI PostAppMessage16( HTASK16 hTask, UINT16 msg, WPARAM16 wparam, LPARAM lparam )
127 {
128     LRESULT unused;
129     DWORD_PTR tid = HTASK_32( hTask );
130
131     if (!tid) return FALSE;
132     return WINPROC_CallProc16To32A( post_thread_message_callback, 0, msg, wparam, lparam,
133                                     &unused, (void *)tid );
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     LRESULT unused;
164     HWND hwnd = WIN_Handle32( hwnd16 );
165
166     if(USER16_AlertableWait)
167         MsgWaitForMultipleObjectsEx( 0, NULL, 1, 0, MWMO_ALERTABLE );
168     if (!PeekMessageA( &msg, hwnd, first, last, flags )) return FALSE;
169
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     WINPROC_CallProc32ATo16( get_message_callback, msg.hwnd, msg.message, msg.wParam, msg.lParam,
175                              &unused, &msg16->msg );
176     return TRUE;
177 }
178
179
180 /***********************************************************************
181  *              DefWindowProc (USER.107)
182  */
183 LRESULT WINAPI DefWindowProc16( HWND16 hwnd16, UINT16 msg, WPARAM16 wParam, LPARAM lParam )
184 {
185     LRESULT result;
186     HWND hwnd = WIN_Handle32( hwnd16 );
187
188     SPY_EnterMessage( SPY_DEFWNDPROC16, hwnd, msg, wParam, lParam );
189
190     switch(msg)
191     {
192     case WM_NCCREATE:
193         {
194             CREATESTRUCT16 *cs16 = MapSL(lParam);
195             CREATESTRUCTA cs32;
196
197             cs32.lpCreateParams = (LPVOID)cs16->lpCreateParams;
198             cs32.hInstance      = HINSTANCE_32(cs16->hInstance);
199             cs32.hMenu          = HMENU_32(cs16->hMenu);
200             cs32.hwndParent     = WIN_Handle32(cs16->hwndParent);
201             cs32.cy             = cs16->cy;
202             cs32.cx             = cs16->cx;
203             cs32.y              = cs16->y;
204             cs32.x              = cs16->x;
205             cs32.style          = cs16->style;
206             cs32.dwExStyle      = cs16->dwExStyle;
207             cs32.lpszName       = MapSL(cs16->lpszName);
208             cs32.lpszClass      = MapSL(cs16->lpszClass);
209             result = DefWindowProcA( hwnd, msg, wParam, (LPARAM)&cs32 );
210         }
211         break;
212
213     case WM_NCCALCSIZE:
214         {
215             RECT16 *rect16 = MapSL(lParam);
216             RECT rect32;
217
218             rect32.left    = rect16->left;
219             rect32.top     = rect16->top;
220             rect32.right   = rect16->right;
221             rect32.bottom  = rect16->bottom;
222
223             result = DefWindowProcA( hwnd, msg, wParam, (LPARAM)&rect32 );
224
225             rect16->left   = rect32.left;
226             rect16->top    = rect32.top;
227             rect16->right  = rect32.right;
228             rect16->bottom = rect32.bottom;
229         }
230         break;
231
232     case WM_WINDOWPOSCHANGING:
233     case WM_WINDOWPOSCHANGED:
234         {
235             WINDOWPOS16 *pos16 = MapSL(lParam);
236             WINDOWPOS pos32;
237
238             pos32.hwnd             = WIN_Handle32(pos16->hwnd);
239             pos32.hwndInsertAfter  = WIN_Handle32(pos16->hwndInsertAfter);
240             pos32.x                = pos16->x;
241             pos32.y                = pos16->y;
242             pos32.cx               = pos16->cx;
243             pos32.cy               = pos16->cy;
244             pos32.flags            = pos16->flags;
245
246             result = DefWindowProcA( hwnd, msg, wParam, (LPARAM)&pos32 );
247
248             pos16->hwnd            = HWND_16(pos32.hwnd);
249             pos16->hwndInsertAfter = HWND_16(pos32.hwndInsertAfter);
250             pos16->x               = pos32.x;
251             pos16->y               = pos32.y;
252             pos16->cx              = pos32.cx;
253             pos16->cy              = pos32.cy;
254             pos16->flags           = pos32.flags;
255         }
256         break;
257
258     case WM_GETTEXT:
259     case WM_SETTEXT:
260         result = DefWindowProcA( hwnd, msg, wParam, (LPARAM)MapSL(lParam) );
261         break;
262
263     default:
264         result = DefWindowProcA( hwnd, msg, wParam, lParam );
265         break;
266     }
267
268     SPY_ExitMessage( SPY_RESULT_DEFWND16, hwnd, msg, result, wParam, lParam );
269     return result;
270 }
271
272
273 /***********************************************************************
274  *              PeekMessage  (USER.109)
275  */
276 BOOL16 WINAPI PeekMessage16( MSG16 *msg, HWND16 hwnd,
277                              UINT16 first, UINT16 last, UINT16 flags )
278 {
279     return PeekMessage32_16( (MSG32_16 *)msg, hwnd, first, last, flags, FALSE );
280 }
281
282
283 /***********************************************************************
284  *              GetMessage32  (USER.820)
285  */
286 BOOL16 WINAPI GetMessage32_16( MSG32_16 *msg16, HWND16 hwnd16, UINT16 first,
287                                UINT16 last, BOOL16 wHaveParamHigh )
288 {
289     MSG msg;
290     LRESULT unused;
291     HWND hwnd = WIN_Handle32( hwnd16 );
292
293     if(USER16_AlertableWait)
294         MsgWaitForMultipleObjectsEx( 0, NULL, INFINITE, 0, MWMO_ALERTABLE );
295     GetMessageA( &msg, hwnd, first, last );
296     msg16->msg.time    = msg.time;
297     msg16->msg.pt.x    = (INT16)msg.pt.x;
298     msg16->msg.pt.y    = (INT16)msg.pt.y;
299     if (wHaveParamHigh) msg16->wParamHigh = HIWORD(msg.wParam);
300     WINPROC_CallProc32ATo16( get_message_callback, msg.hwnd, msg.message, msg.wParam, msg.lParam,
301                              &unused, &msg16->msg );
302
303     TRACE( "message %04x, hwnd %p, filter(%04x - %04x)\n",
304            msg16->msg.message, hwnd, first, last );
305
306     return msg16->msg.message != WM_QUIT;
307 }
308
309
310 /***********************************************************************
311  *              GetMessage  (USER.108)
312  */
313 BOOL16 WINAPI GetMessage16( MSG16 *msg, HWND16 hwnd, UINT16 first, UINT16 last )
314 {
315     return GetMessage32_16( (MSG32_16 *)msg, hwnd, first, last, FALSE );
316 }
317
318
319 /***********************************************************************
320  *              TranslateMessage32 (USER.821)
321  */
322 BOOL16 WINAPI TranslateMessage32_16( const MSG32_16 *msg, BOOL16 wHaveParamHigh )
323 {
324     MSG msg32;
325
326     msg32.hwnd    = WIN_Handle32( msg->msg.hwnd );
327     msg32.message = msg->msg.message;
328     msg32.wParam  = MAKEWPARAM( msg->msg.wParam, wHaveParamHigh ? msg->wParamHigh : 0 );
329     msg32.lParam  = msg->msg.lParam;
330     return TranslateMessage( &msg32 );
331 }
332
333
334 /***********************************************************************
335  *              TranslateMessage (USER.113)
336  */
337 BOOL16 WINAPI TranslateMessage16( const MSG16 *msg )
338 {
339     return TranslateMessage32_16( (const MSG32_16 *)msg, FALSE );
340 }
341
342
343 /***********************************************************************
344  *              DispatchMessage (USER.114)
345  */
346 LONG WINAPI DispatchMessage16( const MSG16* msg )
347 {
348     WND * wndPtr;
349     WNDPROC16 winproc;
350     LONG retval;
351     HWND hwnd = WIN_Handle32( msg->hwnd );
352
353       /* Process timer messages */
354     if ((msg->message == WM_TIMER) || (msg->message == WM_SYSTIMER))
355     {
356         if (msg->lParam)
357             return CallWindowProc16( (WNDPROC16)msg->lParam, msg->hwnd,
358                                      msg->message, msg->wParam, GetTickCount() );
359     }
360
361     if (!(wndPtr = WIN_GetPtr( hwnd )))
362     {
363         if (msg->hwnd) SetLastError( ERROR_INVALID_WINDOW_HANDLE );
364         return 0;
365     }
366     if (wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP)
367     {
368         if (IsWindow( hwnd )) SetLastError( ERROR_MESSAGE_SYNC_ONLY );
369         else SetLastError( ERROR_INVALID_WINDOW_HANDLE );
370         return 0;
371     }
372     winproc = WINPROC_GetProc16( wndPtr->winproc, wndPtr->flags & WIN_ISUNICODE );
373     WIN_ReleasePtr( wndPtr );
374
375     SPY_EnterMessage( SPY_DISPATCHMESSAGE16, hwnd, msg->message, msg->wParam, msg->lParam );
376     retval = CallWindowProc16( winproc, msg->hwnd, msg->message, msg->wParam, msg->lParam );
377     SPY_ExitMessage( SPY_RESULT_OK16, hwnd, msg->message, retval, msg->wParam, msg->lParam );
378
379     return retval;
380 }
381
382
383 /***********************************************************************
384  *              DispatchMessage32 (USER.822)
385  */
386 LONG WINAPI DispatchMessage32_16( const MSG32_16 *msg16, BOOL16 wHaveParamHigh )
387 {
388     if (wHaveParamHigh == FALSE)
389         return DispatchMessage16( &msg16->msg );
390     else
391     {
392         MSG msg;
393
394         msg.hwnd    = WIN_Handle32( msg16->msg.hwnd );
395         msg.message = msg16->msg.message;
396         msg.wParam  = MAKEWPARAM( msg16->msg.wParam, msg16->wParamHigh );
397         msg.lParam  = msg16->msg.lParam;
398         msg.time    = msg16->msg.time;
399         msg.pt.x    = msg16->msg.pt.x;
400         msg.pt.y    = msg16->msg.pt.y;
401         return DispatchMessageA( &msg );
402     }
403 }
404
405
406 /***********************************************************************
407  *              IsDialogMessage (USER.90)
408  */
409 BOOL16 WINAPI IsDialogMessage16( HWND16 hwndDlg, MSG16 *msg16 )
410 {
411     MSG msg;
412     HWND hwndDlg32;
413
414     msg.hwnd  = WIN_Handle32(msg16->hwnd);
415     hwndDlg32 = WIN_Handle32(hwndDlg);
416
417     switch(msg16->message)
418     {
419     case WM_KEYDOWN:
420     case WM_CHAR:
421     case WM_SYSCHAR:
422         msg.message = msg16->message;
423         msg.wParam  = msg16->wParam;
424         msg.lParam  = msg16->lParam;
425         return IsDialogMessageA( hwndDlg32, &msg );
426     }
427
428     if ((hwndDlg32 != msg.hwnd) && !IsChild( hwndDlg32, msg.hwnd )) return FALSE;
429     TranslateMessage16( msg16 );
430     DispatchMessage16( msg16 );
431     return TRUE;
432 }
433
434
435 /***********************************************************************
436  *              MsgWaitForMultipleObjects  (USER.640)
437  */
438 DWORD WINAPI MsgWaitForMultipleObjects16( DWORD count, CONST HANDLE *handles,
439                                           BOOL wait_all, DWORD timeout, DWORD mask )
440 {
441     return MsgWaitForMultipleObjectsEx( count, handles, timeout, mask,
442                                         wait_all ? MWMO_WAITALL : 0 );
443 }
444
445
446 /**********************************************************************
447  *              SetDoubleClickTime (USER.20)
448  */
449 void WINAPI SetDoubleClickTime16( UINT16 interval )
450 {
451     SetDoubleClickTime( interval );
452 }
453
454
455 /**********************************************************************
456  *              GetDoubleClickTime (USER.21)
457  */
458 UINT16 WINAPI GetDoubleClickTime16(void)
459 {
460     return GetDoubleClickTime();
461 }
462
463
464 /***********************************************************************
465  *              PostQuitMessage (USER.6)
466  */
467 void WINAPI PostQuitMessage16( INT16 exitCode )
468 {
469     PostQuitMessage( exitCode );
470 }
471
472
473 /**********************************************************************
474  *              GetKeyState (USER.106)
475  */
476 INT16 WINAPI GetKeyState16(INT16 vkey)
477 {
478     return GetKeyState(vkey);
479 }
480
481
482 /**********************************************************************
483  *              GetKeyboardState (USER.222)
484  */
485 BOOL WINAPI GetKeyboardState16( LPBYTE state )
486 {
487     return GetKeyboardState( state );
488 }
489
490
491 /**********************************************************************
492  *              SetKeyboardState (USER.223)
493  */
494 BOOL WINAPI SetKeyboardState16( LPBYTE state )
495 {
496     return SetKeyboardState( state );
497 }
498
499
500 /***********************************************************************
501  *              SetMessageQueue (USER.266)
502  */
503 BOOL16 WINAPI SetMessageQueue16( INT16 size )
504 {
505     return SetMessageQueue( size );
506 }
507
508
509 /***********************************************************************
510  *              GetQueueStatus (USER.334)
511  */
512 DWORD WINAPI GetQueueStatus16( UINT16 flags )
513 {
514     return GetQueueStatus( flags );
515 }
516
517
518 /***********************************************************************
519  *              GetInputState (USER.335)
520  */
521 BOOL16 WINAPI GetInputState16(void)
522 {
523     return GetInputState();
524 }
525
526
527 /**********************************************************************
528  *           TranslateAccelerator      (USER.178)
529  */
530 INT16 WINAPI TranslateAccelerator16( HWND16 hwnd, HACCEL16 hAccel, LPMSG16 msg )
531 {
532     MSG msg32;
533
534     if (!msg) return 0;
535     msg32.message = msg->message;
536     /* msg32.hwnd not used */
537     msg32.wParam  = msg->wParam;
538     msg32.lParam  = msg->lParam;
539     return TranslateAcceleratorW( WIN_Handle32(hwnd), HACCEL_32(hAccel), &msg32 );
540 }
541
542
543 /**********************************************************************
544  *              TranslateMDISysAccel (USER.451)
545  */
546 BOOL16 WINAPI TranslateMDISysAccel16( HWND16 hwndClient, LPMSG16 msg )
547 {
548     if (msg->message == WM_KEYDOWN || msg->message == WM_SYSKEYDOWN)
549     {
550         MSG msg32;
551         msg32.hwnd    = WIN_Handle32(msg->hwnd);
552         msg32.message = msg->message;
553         msg32.wParam  = msg->wParam;
554         msg32.lParam  = msg->lParam;
555         /* MDICLIENTINFO is still the same for win32 and win16 ... */
556         return TranslateMDISysAccel( WIN_Handle32(hwndClient), &msg32 );
557     }
558     return 0;
559 }