Authors: Rob Shearman <rob@codeweavers.com>, Mike Hearn <mh@codeweavers.com>
[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 "win.h"
26 #include "user_private.h"
27 #include "winproc.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, GWLP_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  *              DefWindowProc (USER.107)
177  */
178 LRESULT WINAPI DefWindowProc16( HWND16 hwnd16, UINT16 msg, WPARAM16 wParam, LPARAM lParam )
179 {
180     LRESULT result;
181     HWND hwnd = WIN_Handle32( hwnd16 );
182
183     SPY_EnterMessage( SPY_DEFWNDPROC16, hwnd, msg, wParam, lParam );
184
185     switch(msg)
186     {
187     case WM_NCCREATE:
188         {
189             CREATESTRUCT16 *cs16 = MapSL(lParam);
190             CREATESTRUCTA cs32;
191
192             cs32.lpCreateParams = (LPVOID)cs16->lpCreateParams;
193             cs32.hInstance      = HINSTANCE_32(cs16->hInstance);
194             cs32.hMenu          = HMENU_32(cs16->hMenu);
195             cs32.hwndParent     = WIN_Handle32(cs16->hwndParent);
196             cs32.cy             = cs16->cy;
197             cs32.cx             = cs16->cx;
198             cs32.y              = cs16->y;
199             cs32.x              = cs16->x;
200             cs32.style          = cs16->style;
201             cs32.dwExStyle      = cs16->dwExStyle;
202             cs32.lpszName       = MapSL(cs16->lpszName);
203             cs32.lpszClass      = MapSL(cs16->lpszClass);
204             result = DefWindowProcA( hwnd, msg, wParam, (LPARAM)&cs32 );
205         }
206         break;
207
208     case WM_NCCALCSIZE:
209         {
210             RECT16 *rect16 = MapSL(lParam);
211             RECT rect32;
212
213             rect32.left    = rect16->left;
214             rect32.top     = rect16->top;
215             rect32.right   = rect16->right;
216             rect32.bottom  = rect16->bottom;
217
218             result = DefWindowProcA( hwnd, msg, wParam, (LPARAM)&rect32 );
219
220             rect16->left   = rect32.left;
221             rect16->top    = rect32.top;
222             rect16->right  = rect32.right;
223             rect16->bottom = rect32.bottom;
224         }
225         break;
226
227     case WM_WINDOWPOSCHANGING:
228     case WM_WINDOWPOSCHANGED:
229         {
230             WINDOWPOS16 *pos16 = MapSL(lParam);
231             WINDOWPOS pos32;
232
233             pos32.hwnd             = WIN_Handle32(pos16->hwnd);
234             pos32.hwndInsertAfter  = WIN_Handle32(pos16->hwndInsertAfter);
235             pos32.x                = pos16->x;
236             pos32.y                = pos16->y;
237             pos32.cx               = pos16->cx;
238             pos32.cy               = pos16->cy;
239             pos32.flags            = pos16->flags;
240
241             result = DefWindowProcA( hwnd, msg, wParam, (LPARAM)&pos32 );
242
243             pos16->hwnd            = HWND_16(pos32.hwnd);
244             pos16->hwndInsertAfter = HWND_16(pos32.hwndInsertAfter);
245             pos16->x               = pos32.x;
246             pos16->y               = pos32.y;
247             pos16->cx              = pos32.cx;
248             pos16->cy              = pos32.cy;
249             pos16->flags           = pos32.flags;
250         }
251         break;
252
253     case WM_GETTEXT:
254     case WM_SETTEXT:
255         result = DefWindowProcA( hwnd, msg, wParam, (LPARAM)MapSL(lParam) );
256         break;
257
258     default:
259         result = DefWindowProcA( hwnd, msg, wParam, lParam );
260         break;
261     }
262
263     SPY_ExitMessage( SPY_RESULT_DEFWND16, hwnd, msg, result, wParam, lParam );
264     return result;
265 }
266
267
268 /***********************************************************************
269  *              PeekMessage  (USER.109)
270  */
271 BOOL16 WINAPI PeekMessage16( MSG16 *msg, HWND16 hwnd,
272                              UINT16 first, UINT16 last, UINT16 flags )
273 {
274     return PeekMessage32_16( (MSG32_16 *)msg, hwnd, first, last, flags, FALSE );
275 }
276
277
278 /***********************************************************************
279  *              GetMessage32  (USER.820)
280  */
281 BOOL16 WINAPI GetMessage32_16( MSG32_16 *msg16, HWND16 hwnd16, UINT16 first,
282                                UINT16 last, BOOL16 wHaveParamHigh )
283 {
284     MSG msg;
285     HWND hwnd = WIN_Handle32( hwnd16 );
286
287     do
288     {
289         if(USER16_AlertableWait)
290             MsgWaitForMultipleObjectsEx( 0, NULL, INFINITE, 0, MWMO_ALERTABLE );
291         GetMessageW( &msg, hwnd, first, last );
292         msg16->msg.hwnd    = HWND_16( msg.hwnd );
293         msg16->msg.lParam  = msg.lParam;
294         msg16->msg.time    = msg.time;
295         msg16->msg.pt.x    = (INT16)msg.pt.x;
296         msg16->msg.pt.y    = (INT16)msg.pt.y;
297         if (wHaveParamHigh) msg16->wParamHigh = HIWORD(msg.wParam);
298     }
299     while (WINPROC_MapMsg32WTo16( msg.hwnd, msg.message, msg.wParam,
300                                   &msg16->msg.message, &msg16->msg.wParam,
301                                   &msg16->msg.lParam ) == -1);
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)
367     {
368         if (IsWindow( hwnd ))
369             ERR( "cannot dispatch msg to other process window %p\n", hwnd );
370         SetLastError( ERROR_INVALID_WINDOW_HANDLE );
371         return 0;
372     }
373     winproc = (WNDPROC16)wndPtr->winproc;
374     WIN_ReleasePtr( wndPtr );
375
376     SPY_EnterMessage( SPY_DISPATCHMESSAGE16, hwnd, msg->message, msg->wParam, msg->lParam );
377     retval = CallWindowProc16( winproc, msg->hwnd, msg->message, msg->wParam, msg->lParam );
378     SPY_ExitMessage( SPY_RESULT_OK16, hwnd, msg->message, retval, msg->wParam, msg->lParam );
379
380     return retval;
381 }
382
383
384 /***********************************************************************
385  *              DispatchMessage32 (USER.822)
386  */
387 LONG WINAPI DispatchMessage32_16( const MSG32_16 *msg16, BOOL16 wHaveParamHigh )
388 {
389     if (wHaveParamHigh == FALSE)
390         return DispatchMessage16( &msg16->msg );
391     else
392     {
393         MSG msg;
394
395         msg.hwnd    = WIN_Handle32( msg16->msg.hwnd );
396         msg.message = msg16->msg.message;
397         msg.wParam  = MAKEWPARAM( msg16->msg.wParam, msg16->wParamHigh );
398         msg.lParam  = msg16->msg.lParam;
399         msg.time    = msg16->msg.time;
400         msg.pt.x    = msg16->msg.pt.x;
401         msg.pt.y    = msg16->msg.pt.y;
402         return DispatchMessageA( &msg );
403     }
404 }
405
406
407 /***********************************************************************
408  *              IsDialogMessage (USER.90)
409  */
410 BOOL16 WINAPI IsDialogMessage16( HWND16 hwndDlg, MSG16 *msg16 )
411 {
412     MSG msg;
413     HWND hwndDlg32;
414
415     msg.hwnd  = WIN_Handle32(msg16->hwnd);
416     hwndDlg32 = WIN_Handle32(hwndDlg);
417
418     switch(msg16->message)
419     {
420     case WM_KEYDOWN:
421     case WM_CHAR:
422     case WM_SYSCHAR:
423         msg.lParam = msg16->lParam;
424         WINPROC_MapMsg16To32W( msg.hwnd, msg16->message, msg16->wParam,
425                                &msg.message, &msg.wParam, &msg.lParam );
426         /* these messages don't need an unmap */
427         return IsDialogMessageW( hwndDlg32, &msg );
428     }
429
430     if ((hwndDlg32 != msg.hwnd) && !IsChild( hwndDlg32, msg.hwnd )) return FALSE;
431     TranslateMessage16( msg16 );
432     DispatchMessage16( msg16 );
433     return TRUE;
434 }
435
436
437 /***********************************************************************
438  *              MsgWaitForMultipleObjects  (USER.640)
439  */
440 DWORD WINAPI MsgWaitForMultipleObjects16( DWORD count, CONST HANDLE *handles,
441                                           BOOL wait_all, DWORD timeout, DWORD mask )
442 {
443     return MsgWaitForMultipleObjectsEx( count, handles, timeout, mask,
444                                         wait_all ? MWMO_WAITALL : 0 );
445 }
446
447
448 /**********************************************************************
449  *              SetDoubleClickTime (USER.20)
450  */
451 void WINAPI SetDoubleClickTime16( UINT16 interval )
452 {
453     SetDoubleClickTime( interval );
454 }
455
456
457 /**********************************************************************
458  *              GetDoubleClickTime (USER.21)
459  */
460 UINT16 WINAPI GetDoubleClickTime16(void)
461 {
462     return GetDoubleClickTime();
463 }
464
465
466 /***********************************************************************
467  *              PostQuitMessage (USER.6)
468  */
469 void WINAPI PostQuitMessage16( INT16 exitCode )
470 {
471     PostQuitMessage( exitCode );
472 }
473
474
475 /**********************************************************************
476  *              GetKeyState (USER.106)
477  */
478 INT16 WINAPI GetKeyState16(INT16 vkey)
479 {
480     return GetKeyState(vkey);
481 }
482
483
484 /**********************************************************************
485  *              GetKeyboardState (USER.222)
486  */
487 BOOL WINAPI GetKeyboardState16( LPBYTE state )
488 {
489     return GetKeyboardState( state );
490 }
491
492
493 /**********************************************************************
494  *              SetKeyboardState (USER.223)
495  */
496 BOOL WINAPI SetKeyboardState16( LPBYTE state )
497 {
498     return SetKeyboardState( state );
499 }
500
501
502 /***********************************************************************
503  *              SetMessageQueue (USER.266)
504  */
505 BOOL16 WINAPI SetMessageQueue16( INT16 size )
506 {
507     return SetMessageQueue( size );
508 }
509
510
511 /***********************************************************************
512  *              GetQueueStatus (USER.334)
513  */
514 DWORD WINAPI GetQueueStatus16( UINT16 flags )
515 {
516     return GetQueueStatus( flags );
517 }
518
519
520 /***********************************************************************
521  *              GetInputState (USER.335)
522  */
523 BOOL16 WINAPI GetInputState16(void)
524 {
525     return GetInputState();
526 }
527
528
529 /**********************************************************************
530  *           TranslateAccelerator      (USER.178)
531  */
532 INT16 WINAPI TranslateAccelerator16( HWND16 hwnd, HACCEL16 hAccel, LPMSG16 msg )
533 {
534     MSG msg32;
535
536     if (!msg) return 0;
537     msg32.message = msg->message;
538     /* msg32.hwnd not used */
539     msg32.wParam  = msg->wParam;
540     msg32.lParam  = msg->lParam;
541     return TranslateAcceleratorW( WIN_Handle32(hwnd), HACCEL_32(hAccel), &msg32 );
542 }
543
544
545 /**********************************************************************
546  *              TranslateMDISysAccel (USER.451)
547  */
548 BOOL16 WINAPI TranslateMDISysAccel16( HWND16 hwndClient, LPMSG16 msg )
549 {
550     if (msg->message == WM_KEYDOWN || msg->message == WM_SYSKEYDOWN)
551     {
552         MSG msg32;
553         msg32.hwnd    = WIN_Handle32(msg->hwnd);
554         msg32.message = msg->message;
555         msg32.wParam  = msg->wParam;
556         msg32.lParam  = msg->lParam;
557         /* MDICLIENTINFO is still the same for win32 and win16 ... */
558         return TranslateMDISysAccel( WIN_Handle32(hwndClient), &msg32 );
559     }
560     return 0;
561 }