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