Reboot (int19) under DOS now does ExitProcess.
[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 "winproc.h"
27 #include "wine/debug.h"
28
29 WINE_DEFAULT_DEBUG_CHANNEL(msg);
30
31 DWORD USER16_AlertableWait = 0;
32
33 /***********************************************************************
34  *              SendMessage  (USER.111)
35  */
36 LRESULT WINAPI SendMessage16( HWND16 hwnd16, UINT16 msg, WPARAM16 wparam, LPARAM lparam )
37 {
38     LRESULT result;
39     UINT msg32;
40     WPARAM wparam32;
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             LPARAM lparam32 = lparam;
52
53             if (WINPROC_MapMsg16To32A( hwnd, msg, wparam, &msg32, &wparam32, &lparam32 ) != -1)
54             {
55                 CWPSTRUCT cwp;
56
57                 cwp.hwnd    = hwnd;
58                 cwp.message = msg32;
59                 cwp.wParam  = wparam32;
60                 cwp.lParam  = lparam32;
61                 HOOK_CallHooks( WH_CALLWNDPROC, HC_ACTION, 1, (LPARAM)&cwp, FALSE );
62                 WINPROC_UnmapMsg16To32A( hwnd, msg32, wparam32, lparam32, 0 );
63                 /* FIXME: should reflect changes back into the message we send */
64             }
65         }
66
67         if (!(winproc = (WNDPROC16)GetWindowLong16( hwnd16, GWL_WNDPROC ))) return 0;
68
69         SPY_EnterMessage( SPY_SENDMESSAGE16, hwnd, msg, wparam, lparam );
70         result = CallWindowProc16( (WNDPROC16)winproc, hwnd16, msg, wparam, lparam );
71         SPY_ExitMessage( SPY_RESULT_OK16, hwnd, msg, result, wparam, lparam );
72     }
73     else  /* map to 32-bit unicode for inter-thread/process message */
74     {
75         if (WINPROC_MapMsg16To32W( hwnd, msg, wparam, &msg32, &wparam32, &lparam ) == -1)
76             return 0;
77         result = WINPROC_UnmapMsg16To32W( hwnd, msg32, wparam32, lparam,
78                                           SendMessageW( hwnd, msg32, wparam32, lparam ) );
79     }
80     return result;
81 }
82
83
84 /***********************************************************************
85  *              PostMessage  (USER.110)
86  */
87 BOOL16 WINAPI PostMessage16( HWND16 hwnd16, UINT16 msg, WPARAM16 wparam, LPARAM lparam )
88 {
89     WPARAM wparam32;
90     UINT msg32;
91     HWND hwnd = WIN_Handle32( hwnd16 );
92
93     switch (WINPROC_MapMsg16To32W( hwnd, msg, wparam, &msg32, &wparam32, &lparam ))
94     {
95     case 0:
96         return PostMessageW( hwnd, msg32, wparam32, lparam );
97     case 1:
98         ERR( "16-bit message 0x%04x contains pointer, cannot post\n", msg );
99         return FALSE;
100     default:
101         return FALSE;
102     }
103 }
104
105
106 /***********************************************************************
107  *              PostAppMessage (USER.116)
108  */
109 BOOL16 WINAPI PostAppMessage16( HTASK16 hTask, UINT16 msg, WPARAM16 wparam, LPARAM lparam )
110 {
111     WPARAM wparam32;
112     UINT msg32;
113     DWORD tid = HTASK_32( hTask );
114     if (!tid) return FALSE;
115
116     switch (WINPROC_MapMsg16To32W( 0, msg, wparam, &msg32, &wparam32, &lparam ))
117     {
118     case 0:
119         return PostThreadMessageW( tid, msg32, wparam32, lparam );
120     case 1:
121         ERR( "16-bit message %x contains pointer, cannot post\n", msg );
122         return FALSE;
123     default:
124         return FALSE;
125     }
126 }
127
128
129 /***********************************************************************
130  *              InSendMessage  (USER.192)
131  */
132 BOOL16 WINAPI InSendMessage16(void)
133 {
134     return InSendMessage();
135 }
136
137
138 /***********************************************************************
139  *              ReplyMessage  (USER.115)
140  */
141 void WINAPI ReplyMessage16( LRESULT result )
142 {
143     ReplyMessage( result );
144 }
145
146
147 /***********************************************************************
148  *              PeekMessage32 (USER.819)
149  */
150 BOOL16 WINAPI PeekMessage32_16( MSG32_16 *msg16, HWND16 hwnd16,
151                                 UINT16 first, UINT16 last, UINT16 flags,
152                                 BOOL16 wHaveParamHigh )
153 {
154     MSG msg;
155     HWND hwnd = WIN_Handle32( hwnd16 );
156
157     if(USER16_AlertableWait)
158         MsgWaitForMultipleObjectsEx( 0, NULL, 1, 0, MWMO_ALERTABLE );
159     if (!PeekMessageW( &msg, hwnd, first, last, flags )) return FALSE;
160
161     msg16->msg.hwnd    = HWND_16( msg.hwnd );
162     msg16->msg.lParam  = msg.lParam;
163     msg16->msg.time    = msg.time;
164     msg16->msg.pt.x    = (INT16)msg.pt.x;
165     msg16->msg.pt.y    = (INT16)msg.pt.y;
166     if (wHaveParamHigh) msg16->wParamHigh = HIWORD(msg.wParam);
167
168     return (WINPROC_MapMsg32WTo16( msg.hwnd, msg.message, msg.wParam,
169                                    &msg16->msg.message, &msg16->msg.wParam,
170                                    &msg16->msg.lParam ) != -1);
171 }
172
173
174 /***********************************************************************
175  *              PeekMessage  (USER.109)
176  */
177 BOOL16 WINAPI PeekMessage16( MSG16 *msg, HWND16 hwnd,
178                              UINT16 first, UINT16 last, UINT16 flags )
179 {
180     return PeekMessage32_16( (MSG32_16 *)msg, hwnd, first, last, flags, FALSE );
181 }
182
183
184 /***********************************************************************
185  *              GetMessage32  (USER.820)
186  */
187 BOOL16 WINAPI GetMessage32_16( MSG32_16 *msg16, HWND16 hwnd16, UINT16 first,
188                                UINT16 last, BOOL16 wHaveParamHigh )
189 {
190     MSG msg;
191     HWND hwnd = WIN_Handle32( hwnd16 );
192
193     do
194     {
195         if(USER16_AlertableWait)
196             MsgWaitForMultipleObjectsEx( 0, NULL, INFINITE, 0, MWMO_ALERTABLE );
197         GetMessageW( &msg, hwnd, first, last );
198         msg16->msg.hwnd    = HWND_16( msg.hwnd );
199         msg16->msg.lParam  = msg.lParam;
200         msg16->msg.time    = msg.time;
201         msg16->msg.pt.x    = (INT16)msg.pt.x;
202         msg16->msg.pt.y    = (INT16)msg.pt.y;
203         if (wHaveParamHigh) msg16->wParamHigh = HIWORD(msg.wParam);
204     }
205     while (WINPROC_MapMsg32WTo16( msg.hwnd, msg.message, msg.wParam,
206                                   &msg16->msg.message, &msg16->msg.wParam,
207                                   &msg16->msg.lParam ) == -1);
208
209     TRACE( "message %04x, hwnd %p, filter(%04x - %04x)\n",
210            msg16->msg.message, hwnd, first, last );
211
212     return msg16->msg.message != WM_QUIT;
213 }
214
215
216 /***********************************************************************
217  *              GetMessage  (USER.108)
218  */
219 BOOL16 WINAPI GetMessage16( MSG16 *msg, HWND16 hwnd, UINT16 first, UINT16 last )
220 {
221     return GetMessage32_16( (MSG32_16 *)msg, hwnd, first, last, FALSE );
222 }
223
224
225 /***********************************************************************
226  *              TranslateMessage32 (USER.821)
227  */
228 BOOL16 WINAPI TranslateMessage32_16( const MSG32_16 *msg, BOOL16 wHaveParamHigh )
229 {
230     MSG msg32;
231
232     msg32.hwnd    = WIN_Handle32( msg->msg.hwnd );
233     msg32.message = msg->msg.message;
234     msg32.wParam  = MAKEWPARAM( msg->msg.wParam, wHaveParamHigh ? msg->wParamHigh : 0 );
235     msg32.lParam  = msg->msg.lParam;
236     return TranslateMessage( &msg32 );
237 }
238
239
240 /***********************************************************************
241  *              TranslateMessage (USER.113)
242  */
243 BOOL16 WINAPI TranslateMessage16( const MSG16 *msg )
244 {
245     return TranslateMessage32_16( (MSG32_16 *)msg, FALSE );
246 }
247
248
249 /***********************************************************************
250  *              DispatchMessage (USER.114)
251  */
252 LONG WINAPI DispatchMessage16( const MSG16* msg )
253 {
254     WND * wndPtr;
255     WNDPROC16 winproc;
256     LONG retval;
257     int painting;
258     HWND hwnd = WIN_Handle32( msg->hwnd );
259
260       /* Process timer messages */
261     if ((msg->message == WM_TIMER) || (msg->message == WM_SYSTIMER))
262     {
263         if (msg->lParam)
264         {
265             /* before calling window proc, verify whether timer is still valid;
266                there's a slim chance that the application kills the timer
267                between GetMessage and DispatchMessage API calls */
268             if (!TIMER_IsTimerValid(hwnd, (UINT) msg->wParam, (WNDPROC)msg->lParam))
269                 return 0; /* invalid winproc */
270
271             return CallWindowProc16( (WNDPROC16)msg->lParam, msg->hwnd,
272                                      msg->message, msg->wParam, GetTickCount() );
273         }
274     }
275
276     if (!(wndPtr = WIN_GetPtr( hwnd )))
277     {
278         if (msg->hwnd) SetLastError( ERROR_INVALID_WINDOW_HANDLE );
279         return 0;
280     }
281     if (wndPtr == WND_OTHER_PROCESS)
282     {
283         if (IsWindow( hwnd ))
284             ERR( "cannot dispatch msg to other process window %p\n", hwnd );
285         SetLastError( ERROR_INVALID_WINDOW_HANDLE );
286         return 0;
287     }
288
289     if (!(winproc = (WNDPROC16)wndPtr->winproc))
290     {
291         WIN_ReleasePtr( wndPtr );
292         return 0;
293     }
294     painting = (msg->message == WM_PAINT);
295     if (painting) wndPtr->flags |= WIN_NEEDS_BEGINPAINT;
296     WIN_ReleasePtr( wndPtr );
297
298     SPY_EnterMessage( SPY_DISPATCHMESSAGE16, hwnd, msg->message, msg->wParam, msg->lParam );
299     retval = CallWindowProc16( winproc, msg->hwnd, msg->message, msg->wParam, msg->lParam );
300     SPY_ExitMessage( SPY_RESULT_OK16, hwnd, msg->message, retval, msg->wParam, msg->lParam );
301
302     if (painting && (wndPtr = WIN_GetPtr( hwnd )) && (wndPtr != WND_OTHER_PROCESS))
303     {
304         BOOL validate = ((wndPtr->flags & WIN_NEEDS_BEGINPAINT) && wndPtr->hrgnUpdate);
305         wndPtr->flags &= ~WIN_NEEDS_BEGINPAINT;
306         WIN_ReleasePtr( wndPtr );
307         if (validate)
308         {
309             ERR( "BeginPaint not called on WM_PAINT for hwnd %p!\n", hwnd );
310             /* Validate the update region to avoid infinite WM_PAINT loop */
311             RedrawWindow( hwnd, NULL, 0,
312                           RDW_NOFRAME | RDW_VALIDATE | RDW_NOCHILDREN | RDW_NOINTERNALPAINT );
313         }
314     }
315     return retval;
316 }
317
318
319 /***********************************************************************
320  *              DispatchMessage32 (USER.822)
321  */
322 LONG WINAPI DispatchMessage32_16( const MSG32_16 *msg16, BOOL16 wHaveParamHigh )
323 {
324     if (wHaveParamHigh == FALSE)
325         return DispatchMessage16( &msg16->msg );
326     else
327     {
328         MSG msg;
329
330         msg.hwnd    = WIN_Handle32( msg16->msg.hwnd );
331         msg.message = msg16->msg.message;
332         msg.wParam  = MAKEWPARAM( msg16->msg.wParam, msg16->wParamHigh );
333         msg.lParam  = msg16->msg.lParam;
334         msg.time    = msg16->msg.time;
335         msg.pt.x    = msg16->msg.pt.x;
336         msg.pt.y    = msg16->msg.pt.y;
337         return DispatchMessageA( &msg );
338     }
339 }
340
341
342 /***********************************************************************
343  *              IsDialogMessage (USER.90)
344  */
345 BOOL16 WINAPI IsDialogMessage16( HWND16 hwndDlg, MSG16 *msg16 )
346 {
347     MSG msg;
348
349     switch(msg16->message)
350     {
351     case WM_KEYDOWN:
352     case WM_CHAR:
353     case WM_SYSCHAR:
354         msg.hwnd   = WIN_Handle32(msg16->hwnd);
355         msg.lParam = msg16->lParam;
356         WINPROC_MapMsg16To32W( msg.hwnd, msg16->message, msg16->wParam,
357                                &msg.message, &msg.wParam, &msg.lParam );
358         /* these messages don't need an unmap */
359         return IsDialogMessageW( WIN_Handle32(hwndDlg), &msg );
360     }
361     TranslateMessage16( msg16 );
362     DispatchMessage16( msg16 );
363     return TRUE;
364 }
365
366
367 /***********************************************************************
368  *              MsgWaitForMultipleObjects  (USER.640)
369  */
370 DWORD WINAPI MsgWaitForMultipleObjects16( DWORD count, CONST HANDLE *handles,
371                                           BOOL wait_all, DWORD timeout, DWORD mask )
372 {
373     return MsgWaitForMultipleObjectsEx( count, handles, timeout, mask,
374                                         wait_all ? MWMO_WAITALL : 0 );
375 }
376
377
378 /**********************************************************************
379  *              SetDoubleClickTime (USER.20)
380  */
381 void WINAPI SetDoubleClickTime16( UINT16 interval )
382 {
383     SetDoubleClickTime( interval );
384 }
385
386
387 /**********************************************************************
388  *              GetDoubleClickTime (USER.21)
389  */
390 UINT16 WINAPI GetDoubleClickTime16(void)
391 {
392     return GetDoubleClickTime();
393 }
394
395
396 /***********************************************************************
397  *              PostQuitMessage (USER.6)
398  */
399 void WINAPI PostQuitMessage16( INT16 exitCode )
400 {
401     PostQuitMessage( exitCode );
402 }
403
404
405 /**********************************************************************
406  *              GetKeyState (USER.106)
407  */
408 INT16 WINAPI GetKeyState16(INT16 vkey)
409 {
410     return GetKeyState(vkey);
411 }
412
413
414 /**********************************************************************
415  *              GetKeyboardState (USER.222)
416  */
417 BOOL WINAPI GetKeyboardState16( LPBYTE state )
418 {
419     return GetKeyboardState( state );
420 }
421
422
423 /**********************************************************************
424  *              SetKeyboardState (USER.223)
425  */
426 BOOL WINAPI SetKeyboardState16( LPBYTE state )
427 {
428     return SetKeyboardState( state );
429 }
430
431
432 /***********************************************************************
433  *              SetMessageQueue (USER.266)
434  */
435 BOOL16 WINAPI SetMessageQueue16( INT16 size )
436 {
437     return SetMessageQueue( size );
438 }
439
440
441 /***********************************************************************
442  *              GetQueueStatus (USER.334)
443  */
444 DWORD WINAPI GetQueueStatus16( UINT16 flags )
445 {
446     return GetQueueStatus( flags );
447 }
448
449
450 /***********************************************************************
451  *              GetInputState (USER.335)
452  */
453 BOOL16 WINAPI GetInputState16(void)
454 {
455     return GetInputState();
456 }
457
458
459 /**********************************************************************
460  *           TranslateAccelerator      (USER.178)
461  */
462 INT16 WINAPI TranslateAccelerator16( HWND16 hwnd, HACCEL16 hAccel, LPMSG16 msg )
463 {
464     MSG msg32;
465
466     if (!msg) return 0;
467     msg32.message = msg->message;
468     /* msg32.hwnd not used */
469     msg32.wParam  = msg->wParam;
470     msg32.lParam  = msg->lParam;
471     return TranslateAccelerator( WIN_Handle32(hwnd), HACCEL_32(hAccel), &msg32 );
472 }
473
474
475 /**********************************************************************
476  *              TranslateMDISysAccel (USER.451)
477  */
478 BOOL16 WINAPI TranslateMDISysAccel16( HWND16 hwndClient, LPMSG16 msg )
479 {
480     if (msg->message == WM_KEYDOWN || msg->message == WM_SYSKEYDOWN)
481     {
482         MSG msg32;
483         msg32.hwnd    = WIN_Handle32(msg->hwnd);
484         msg32.message = msg->message;
485         msg32.wParam  = msg->wParam;
486         msg32.lParam  = msg->lParam;
487         /* MDICLIENTINFO is still the same for win32 and win16 ... */
488         return TranslateMDISysAccel( WIN_Handle32(hwndClient), &msg32 );
489     }
490     return 0;
491 }