- Don't string copy from uninitialised stack memory. In fact don't
[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 "winerror.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 DWORD USER16_AlertableWait = 0;
20
21 /***********************************************************************
22  *              SendMessage  (USER.111)
23  */
24 LRESULT WINAPI SendMessage16( HWND16 hwnd16, UINT16 msg, WPARAM16 wparam, LPARAM lparam )
25 {
26     LRESULT result;
27     HWND hwnd = WIN_Handle32( hwnd16 );
28
29     if (hwnd != HWND_BROADCAST && WIN_IsCurrentThread(hwnd))
30     {
31         /* call 16-bit window proc directly */
32         WNDPROC16 winproc;
33
34         /* first the WH_CALLWNDPROC hook */
35         if (HOOK_IsHooked( WH_CALLWNDPROC ))
36         {
37             CWPSTRUCT16 cwp;
38             SEGPTR seg_cwp;
39
40             cwp.hwnd    = hwnd16;
41             cwp.message = msg;
42             cwp.wParam  = wparam;
43             cwp.lParam  = lparam;
44             seg_cwp = MapLS( &cwp );
45             HOOK_CallHooks16( WH_CALLWNDPROC, HC_ACTION, 1, seg_cwp );
46             UnMapLS( seg_cwp );
47             if (cwp.hwnd != hwnd16)
48             {
49                 hwnd16 = cwp.hwnd;
50                 hwnd = WIN_Handle32( hwnd16 );
51             }
52             msg    = cwp.message;
53             wparam = cwp.wParam;
54             lparam = cwp.lParam;
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(USER16_AlertableWait)
152         MsgWaitForMultipleObjectsEx( 0, NULL, 1, 0, MWMO_ALERTABLE );
153     if (!PeekMessageW( &msg, hwnd, first, last, flags )) return FALSE;
154
155     msg16->msg.hwnd    = WIN_Handle16( msg.hwnd );
156     msg16->msg.lParam  = msg.lParam;
157     msg16->msg.time    = msg.time;
158     msg16->msg.pt.x    = (INT16)msg.pt.x;
159     msg16->msg.pt.y    = (INT16)msg.pt.y;
160     if (wHaveParamHigh) msg16->wParamHigh = HIWORD(msg.wParam);
161
162     return (WINPROC_MapMsg32WTo16( msg.hwnd, msg.message, msg.wParam,
163                                    &msg16->msg.message, &msg16->msg.wParam,
164                                    &msg16->msg.lParam ) != -1);
165 }
166
167
168 /***********************************************************************
169  *              PeekMessage  (USER.109)
170  */
171 BOOL16 WINAPI PeekMessage16( MSG16 *msg, HWND16 hwnd,
172                              UINT16 first, UINT16 last, UINT16 flags )
173 {
174     return PeekMessage32_16( (MSG32_16 *)msg, hwnd, first, last, flags, FALSE );
175 }
176
177
178 /***********************************************************************
179  *              GetMessage32  (USER.820)
180  */
181 BOOL16 WINAPI GetMessage32_16( MSG32_16 *msg16, HWND16 hwnd16, UINT16 first,
182                                UINT16 last, BOOL16 wHaveParamHigh )
183 {
184     MSG msg;
185     HWND hwnd = WIN_Handle32( hwnd16 );
186
187     do
188     {
189         if(USER16_AlertableWait)
190             MsgWaitForMultipleObjectsEx( 0, NULL, INFINITE, 0, MWMO_ALERTABLE );
191         GetMessageW( &msg, hwnd, first, last );
192         msg16->msg.hwnd    = WIN_Handle16( msg.hwnd );
193         msg16->msg.lParam  = msg.lParam;
194         msg16->msg.time    = msg.time;
195         msg16->msg.pt.x    = (INT16)msg.pt.x;
196         msg16->msg.pt.y    = (INT16)msg.pt.y;
197         if (wHaveParamHigh) msg16->wParamHigh = HIWORD(msg.wParam);
198     }
199     while (WINPROC_MapMsg32WTo16( msg.hwnd, msg.message, msg.wParam,
200                                   &msg16->msg.message, &msg16->msg.wParam,
201                                   &msg16->msg.lParam ) == -1);
202
203     TRACE( "message %04x, hwnd %04x, filter(%04x - %04x)\n",
204            msg16->msg.message, hwnd, first, last );
205
206     return msg16->msg.message != WM_QUIT;
207 }
208
209
210 /***********************************************************************
211  *              GetMessage  (USER.108)
212  */
213 BOOL16 WINAPI GetMessage16( MSG16 *msg, HWND16 hwnd, UINT16 first, UINT16 last )
214 {
215     return GetMessage32_16( (MSG32_16 *)msg, hwnd, first, last, FALSE );
216 }
217
218
219 /***********************************************************************
220  *              TranslateMessage32 (USER.821)
221  */
222 BOOL16 WINAPI TranslateMessage32_16( const MSG32_16 *msg, BOOL16 wHaveParamHigh )
223 {
224     MSG msg32;
225
226     msg32.hwnd    = WIN_Handle32( msg->msg.hwnd );
227     msg32.message = msg->msg.message;
228     msg32.wParam  = MAKEWPARAM( msg->msg.wParam, wHaveParamHigh ? msg->wParamHigh : 0 );
229     msg32.lParam  = msg->msg.lParam;
230     return TranslateMessage( &msg32 );
231 }
232
233
234 /***********************************************************************
235  *              TranslateMessage (USER.113)
236  */
237 BOOL16 WINAPI TranslateMessage16( const MSG16 *msg )
238 {
239     return TranslateMessage32_16( (MSG32_16 *)msg, FALSE );
240 }
241
242
243 /***********************************************************************
244  *              DispatchMessage (USER.114)
245  */
246 LONG WINAPI DispatchMessage16( const MSG16* msg )
247 {
248     WND * wndPtr;
249     WNDPROC16 winproc;
250     LONG retval;
251     int painting;
252     HWND hwnd = WIN_Handle32( msg->hwnd );
253
254       /* Process timer messages */
255     if ((msg->message == WM_TIMER) || (msg->message == WM_SYSTIMER))
256     {
257         if (msg->lParam)
258         {
259             /* before calling window proc, verify whether timer is still valid;
260                there's a slim chance that the application kills the timer
261                between GetMessage and DispatchMessage API calls */
262             if (!TIMER_IsTimerValid(hwnd, (UINT) msg->wParam, (HWINDOWPROC) msg->lParam))
263                 return 0; /* invalid winproc */
264
265             return CallWindowProc16( (WNDPROC16)msg->lParam, msg->hwnd,
266                                      msg->message, msg->wParam, GetTickCount() );
267         }
268     }
269
270     if (!(wndPtr = WIN_GetPtr( msg->hwnd )))
271     {
272         if (msg->hwnd) SetLastError( ERROR_INVALID_WINDOW_HANDLE );
273         return 0;
274     }
275     if (wndPtr == WND_OTHER_PROCESS)
276     {
277         if (IsWindow( msg->hwnd ))
278             ERR( "cannot dispatch msg to other process window %x\n", msg->hwnd );
279         SetLastError( ERROR_INVALID_WINDOW_HANDLE );
280         return 0;
281     }
282
283     if (!(winproc = (WNDPROC16)wndPtr->winproc))
284     {
285         WIN_ReleasePtr( wndPtr );
286         return 0;
287     }
288     painting = (msg->message == WM_PAINT);
289     if (painting) wndPtr->flags |= WIN_NEEDS_BEGINPAINT;
290     WIN_ReleasePtr( wndPtr );
291
292     SPY_EnterMessage( SPY_DISPATCHMESSAGE16, hwnd, msg->message, msg->wParam, msg->lParam );
293     retval = CallWindowProc16( winproc, msg->hwnd, msg->message, msg->wParam, msg->lParam );
294     SPY_ExitMessage( SPY_RESULT_OK16, hwnd, msg->message, retval, msg->wParam, msg->lParam );
295
296     if (painting && (wndPtr = WIN_GetPtr( hwnd )) && (wndPtr != WND_OTHER_PROCESS))
297     {
298         BOOL validate = ((wndPtr->flags & WIN_NEEDS_BEGINPAINT) && wndPtr->hrgnUpdate);
299         wndPtr->flags &= ~WIN_NEEDS_BEGINPAINT;
300         WIN_ReleasePtr( wndPtr );
301         if (validate)
302         {
303             ERR( "BeginPaint not called on WM_PAINT for hwnd %04x!\n", msg->hwnd );
304             /* Validate the update region to avoid infinite WM_PAINT loop */
305             RedrawWindow( hwnd, NULL, 0,
306                           RDW_NOFRAME | RDW_VALIDATE | RDW_NOCHILDREN | RDW_NOINTERNALPAINT );
307         }
308     }
309     return retval;
310 }
311
312
313 /***********************************************************************
314  *              DispatchMessage32 (USER.822)
315  */
316 LONG WINAPI DispatchMessage32_16( const MSG32_16 *msg16, BOOL16 wHaveParamHigh )
317 {
318     if (wHaveParamHigh == FALSE)
319         return DispatchMessage16( &msg16->msg );
320     else
321     {
322         MSG msg;
323
324         msg.hwnd    = WIN_Handle32( msg16->msg.hwnd );
325         msg.message = msg16->msg.message;
326         msg.wParam  = MAKEWPARAM( msg16->msg.wParam, msg16->wParamHigh );
327         msg.lParam  = msg16->msg.lParam;
328         msg.time    = msg16->msg.time;
329         msg.pt.x    = msg16->msg.pt.x;
330         msg.pt.y    = msg16->msg.pt.y;
331         return DispatchMessageA( &msg );
332     }
333 }
334
335
336 /***********************************************************************
337  *              MsgWaitForMultipleObjects  (USER.640)
338  */
339 DWORD WINAPI MsgWaitForMultipleObjects16( DWORD count, CONST HANDLE *handles,
340                                           BOOL wait_all, DWORD timeout, DWORD mask )
341 {
342     return MsgWaitForMultipleObjectsEx( count, handles, timeout, mask,
343                                         wait_all ? MWMO_WAITALL : 0 );
344 }
345
346
347 /**********************************************************************
348  *              SetDoubleClickTime (USER.20)
349  */
350 void WINAPI SetDoubleClickTime16( UINT16 interval )
351 {
352     SetDoubleClickTime( interval );
353 }
354
355
356 /**********************************************************************
357  *              GetDoubleClickTime (USER.21)
358  */
359 UINT16 WINAPI GetDoubleClickTime16(void)
360 {
361     return GetDoubleClickTime();
362 }
363
364
365 /***********************************************************************
366  *              PostQuitMessage (USER.6)
367  */
368 void WINAPI PostQuitMessage16( INT16 exitCode )
369 {
370     PostQuitMessage( exitCode );
371 }
372
373
374 /***********************************************************************
375  *              SetMessageQueue (USER.266)
376  */
377 BOOL16 WINAPI SetMessageQueue16( INT16 size )
378 {
379     return SetMessageQueue( size );
380 }
381
382
383 /***********************************************************************
384  *              GetQueueStatus (USER.334)
385  */
386 DWORD WINAPI GetQueueStatus16( UINT16 flags )
387 {
388     return GetQueueStatus( flags );
389 }
390
391
392 /***********************************************************************
393  *              GetInputState (USER.335)
394  */
395 BOOL16 WINAPI GetInputState16(void)
396 {
397     return GetInputState();
398 }
399
400
401 /**********************************************************************
402  *           TranslateAccelerator      (USER.178)
403  */
404 INT16 WINAPI TranslateAccelerator16( HWND16 hwnd, HACCEL16 hAccel, LPMSG16 msg )
405 {
406     MSG msg32;
407
408     if (!msg) return 0;
409     msg32.message = msg->message;
410     /* msg32.hwnd not used */
411     msg32.wParam  = msg->wParam;
412     msg32.lParam  = msg->lParam;
413     return TranslateAccelerator( WIN_Handle32(hwnd), hAccel, &msg32 );
414 }
415
416
417 /**********************************************************************
418  *              TranslateMDISysAccel (USER.451)
419  */
420 BOOL16 WINAPI TranslateMDISysAccel16( HWND16 hwndClient, LPMSG16 msg )
421 {
422     if (msg->message == WM_KEYDOWN || msg->message == WM_SYSKEYDOWN)
423     {
424         MSG msg32;
425         msg32.hwnd    = WIN_Handle32(msg->hwnd);
426         msg32.message = msg->message;
427         msg32.wParam  = msg->wParam;
428         msg32.lParam  = msg->lParam;
429         /* MDICLIENTINFO is still the same for win32 and win16 ... */
430         return TranslateMDISysAccel( WIN_Handle32(hwndClient), &msg32 );
431     }
432     return 0;
433 }