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