user32/tests: Fix a couple of test failures on Windows.
[wine] / dlls / user32 / hook16.c
1 /*
2  * Windows 16-bit hook functions
3  *
4  * Copyright 1994, 1995, 2002 Alexandre Julliard
5  * Copyright 1996 Andrew Lewycky
6  *
7  * Based on investigations by Alex Korobka
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 2.1 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22  */
23
24 #include <stdarg.h>
25
26 #include "windef.h"
27 #include "winbase.h"
28 #include "winuser.h"
29 #include "wownt32.h"
30 #include "wine/winuser16.h"
31 #include "win.h"
32 #include "user_private.h"
33 #include "wine/debug.h"
34
35 WINE_DEFAULT_DEBUG_CHANNEL(hook);
36
37
38 static LRESULT CALLBACK call_WH_MSGFILTER( INT code, WPARAM wp, LPARAM lp );
39 static LRESULT CALLBACK call_WH_KEYBOARD( INT code, WPARAM wp, LPARAM lp );
40 static LRESULT CALLBACK call_WH_GETMESSAGE( INT code, WPARAM wp, LPARAM lp );
41 static LRESULT CALLBACK call_WH_CALLWNDPROC( INT code, WPARAM wp, LPARAM lp );
42 static LRESULT CALLBACK call_WH_CBT( INT code, WPARAM wp, LPARAM lp );
43 static LRESULT CALLBACK call_WH_MOUSE( INT code, WPARAM wp, LPARAM lp );
44 static LRESULT CALLBACK call_WH_SHELL( INT code, WPARAM wp, LPARAM lp );
45
46 #define WH_MAXHOOK16 WH_SHELL  /* Win16 only supports up to WH_SHELL */
47 #define NB_HOOKS16 (WH_MAXHOOK16 - WH_MINHOOK + 1)
48
49 static const HOOKPROC hook_procs[NB_HOOKS16] =
50 {
51     call_WH_MSGFILTER,   /* WH_MSGFILTER        */
52     NULL,                /* WH_JOURNALRECORD */
53     NULL,                /* WH_JOURNALPLAYBACK */
54     call_WH_KEYBOARD,    /* WH_KEYBOARD */
55     call_WH_GETMESSAGE,  /* WH_GETMESSAGE */
56     call_WH_CALLWNDPROC, /* WH_CALLWNDPROC */
57     call_WH_CBT,         /* WH_CBT */
58     NULL,                /* WH_SYSMSGFILTER */
59     call_WH_MOUSE,       /* WH_MOUSE */
60     NULL,                /* WH_HARDWARE */
61     NULL,                /* WH_DEBUG */
62     call_WH_SHELL        /* WH_SHELL */
63 };
64
65
66 /* this structure is stored in the thread queue */
67 struct hook16_queue_info
68 {
69     INT        id;                /* id of current hook */
70     HHOOK      hook[NB_HOOKS16];  /* Win32 hook handles */
71     HOOKPROC16 proc[NB_HOOKS16];  /* 16-bit hook procedures */
72 };
73
74
75
76 /***********************************************************************
77  *           map_msg_16_to_32
78  */
79 static inline void map_msg_16_to_32( const MSG16 *msg16, MSG *msg32 )
80 {
81     msg32->hwnd    = WIN_Handle32(msg16->hwnd);
82     msg32->message = msg16->message;
83     msg32->wParam  = msg16->wParam;
84     msg32->lParam  = msg16->lParam;
85     msg32->time    = msg16->time;
86     msg32->pt.x    = msg16->pt.x;
87     msg32->pt.y    = msg16->pt.y;
88 }
89
90
91 /***********************************************************************
92  *           map_msg_32_to_16
93  */
94 static inline void map_msg_32_to_16( const MSG *msg32, MSG16 *msg16 )
95 {
96     msg16->hwnd    = HWND_16(msg32->hwnd);
97     msg16->message = msg32->message;
98     msg16->wParam  = msg32->wParam;
99     msg16->lParam  = msg32->lParam;
100     msg16->time    = msg32->time;
101     msg16->pt.x    = msg32->pt.x;
102     msg16->pt.y    = msg32->pt.y;
103 }
104
105
106 /***********************************************************************
107  *           call_hook_16
108  */
109 static LRESULT call_hook_16( INT id, INT code, WPARAM wp, LPARAM lp )
110 {
111     struct hook16_queue_info *info = get_user_thread_info()->hook16_info;
112     WORD args[4];
113     DWORD ret;
114     INT prev_id = info->id;
115     info->id = id;
116
117     args[3] = code;
118     args[2] = wp;
119     args[1] = HIWORD(lp);
120     args[0] = LOWORD(lp);
121     WOWCallback16Ex( (DWORD)info->proc[id - WH_MINHOOK], WCB16_PASCAL, sizeof(args), args, &ret );
122
123     info->id = prev_id;
124
125     /* Grrr. While the hook procedure is supposed to have an LRESULT return
126        value even in Win16, it seems that for those hook types where the
127        return value is interpreted as BOOL, Windows doesn't actually check
128        the HIWORD ...  Some buggy Win16 programs, notably WINFILE, rely on
129        that, because they neglect to clear DX ... */
130     if (id != WH_JOURNALPLAYBACK) ret = LOWORD( ret );
131     return ret;
132 }
133
134
135 struct wndproc_hook_params
136 {
137     HHOOK  hhook;
138     INT    code;
139     WPARAM wparam;
140 };
141
142 /* callback for WINPROC_Call16To32A */
143 static LRESULT wndproc_hook_callback( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp,
144                                       LRESULT *result, void *arg )
145 {
146     struct wndproc_hook_params *params = arg;
147     CWPSTRUCT cwp;
148
149     cwp.hwnd    = hwnd;
150     cwp.message = msg;
151     cwp.wParam  = wp;
152     cwp.lParam  = lp;
153     *result = 0;
154     return CallNextHookEx( params->hhook, params->code, params->wparam, (LPARAM)&cwp );
155 }
156
157 /* callback for WINPROC_Call32ATo16 */
158 static LRESULT wndproc_hook_callback16( HWND16 hwnd, UINT16 msg, WPARAM16 wp, LPARAM lp,
159                                         LRESULT *result, void *arg )
160 {
161     struct wndproc_hook_params *params = arg;
162     CWPSTRUCT16 cwp;
163     LRESULT ret;
164
165     cwp.hwnd    = hwnd;
166     cwp.message = msg;
167     cwp.wParam  = wp;
168     cwp.lParam  = lp;
169
170     lp = MapLS( &cwp );
171     ret = call_hook_16( WH_CALLWNDPROC, params->code, params->wparam, lp );
172     UnMapLS( lp );
173
174     *result = 0;
175     return ret;
176 }
177
178
179 /***********************************************************************
180  *              call_WH_MSGFILTER
181  */
182 static LRESULT CALLBACK call_WH_MSGFILTER( INT code, WPARAM wp, LPARAM lp )
183 {
184     MSG *msg32 = (MSG *)lp;
185     MSG16 msg16;
186     LRESULT ret;
187
188     map_msg_32_to_16( msg32, &msg16 );
189     lp = MapLS( &msg16 );
190     ret = call_hook_16( WH_MSGFILTER, code, wp, lp );
191     UnMapLS( lp );
192     return ret;
193 }
194
195
196 /***********************************************************************
197  *              call_WH_KEYBOARD
198  */
199 static LRESULT CALLBACK call_WH_KEYBOARD( INT code, WPARAM wp, LPARAM lp )
200 {
201     return call_hook_16( WH_KEYBOARD, code, wp, lp );
202 }
203
204
205 /***********************************************************************
206  *              call_WH_GETMESSAGE
207  */
208 static LRESULT CALLBACK call_WH_GETMESSAGE( INT code, WPARAM wp, LPARAM lp )
209 {
210     MSG *msg32 = (MSG *)lp;
211     MSG16 msg16;
212     LRESULT ret;
213
214     map_msg_32_to_16( msg32, &msg16 );
215
216     lp = MapLS( &msg16 );
217     ret = call_hook_16( WH_GETMESSAGE, code, wp, lp );
218     UnMapLS( lp );
219
220     map_msg_16_to_32( &msg16, msg32 );
221     return ret;
222 }
223
224
225 /***********************************************************************
226  *              call_WH_CALLWNDPROC
227  */
228 static LRESULT CALLBACK call_WH_CALLWNDPROC( INT code, WPARAM wp, LPARAM lp )
229 {
230     struct wndproc_hook_params params;
231     CWPSTRUCT *cwp32 = (CWPSTRUCT *)lp;
232     LRESULT result;
233
234     params.code   = code;
235     params.wparam = wp;
236     return WINPROC_CallProc32ATo16( wndproc_hook_callback16, cwp32->hwnd, cwp32->message,
237                                     cwp32->wParam, cwp32->lParam, &result, &params );
238 }
239
240
241 /***********************************************************************
242  *              call_WH_CBT
243  */
244 static LRESULT CALLBACK call_WH_CBT( INT code, WPARAM wp, LPARAM lp )
245 {
246     LRESULT ret = 0;
247
248     switch (code)
249     {
250     case HCBT_CREATEWND:
251         {
252             CBT_CREATEWNDA *cbtcw32 = (CBT_CREATEWNDA *)lp;
253             CBT_CREATEWND16 cbtcw16;
254             CREATESTRUCT16 cs16;
255
256             cs16.lpCreateParams = (SEGPTR)cbtcw32->lpcs->lpCreateParams;
257             cs16.hInstance      = HINSTANCE_16(cbtcw32->lpcs->hInstance);
258             cs16.hMenu          = HMENU_16(cbtcw32->lpcs->hMenu);
259             cs16.hwndParent     = HWND_16(cbtcw32->lpcs->hwndParent);
260             cs16.cy             = cbtcw32->lpcs->cy;
261             cs16.cx             = cbtcw32->lpcs->cx;
262             cs16.y              = cbtcw32->lpcs->y;
263             cs16.x              = cbtcw32->lpcs->x;
264             cs16.style          = cbtcw32->lpcs->style;
265             cs16.lpszName       = MapLS( cbtcw32->lpcs->lpszName );
266             cs16.lpszClass      = MapLS( cbtcw32->lpcs->lpszClass );
267             cs16.dwExStyle      = cbtcw32->lpcs->dwExStyle;
268
269             cbtcw16.lpcs = (CREATESTRUCT16 *)MapLS( &cs16 );
270             cbtcw16.hwndInsertAfter = HWND_16( cbtcw32->hwndInsertAfter );
271
272             lp = MapLS( &cbtcw16 );
273             ret = call_hook_16( WH_CBT, code, wp, lp );
274             UnMapLS( cs16.lpszName );
275             UnMapLS( cs16.lpszClass );
276
277             cbtcw32->hwndInsertAfter = WIN_Handle32( cbtcw16.hwndInsertAfter );
278             UnMapLS( (SEGPTR)cbtcw16.lpcs );
279             UnMapLS( lp );
280             break;
281         }
282
283     case HCBT_ACTIVATE:
284         {
285             CBTACTIVATESTRUCT *cas32 = (CBTACTIVATESTRUCT *)lp;
286             CBTACTIVATESTRUCT16 cas16;
287
288             cas16.fMouse     = cas32->fMouse;
289             cas16.hWndActive = HWND_16( cas32->hWndActive );
290
291             lp = MapLS( &cas16 );
292             ret = call_hook_16( WH_CBT, code, wp, lp );
293             UnMapLS( lp );
294             break;
295         }
296     case HCBT_CLICKSKIPPED:
297         {
298             MOUSEHOOKSTRUCT *ms32 = (MOUSEHOOKSTRUCT *)lp;
299             MOUSEHOOKSTRUCT16 ms16;
300
301             ms16.pt.x         = ms32->pt.x;
302             ms16.pt.y         = ms32->pt.y;
303             ms16.hwnd         = HWND_16( ms32->hwnd );
304             ms16.wHitTestCode = ms32->wHitTestCode;
305             ms16.dwExtraInfo  = ms32->dwExtraInfo;
306
307             lp = MapLS( &ms16 );
308             ret = call_hook_16( WH_CBT, code, wp, lp );
309             UnMapLS( lp );
310             break;
311         }
312     case HCBT_MOVESIZE:
313         {
314             RECT *rect32 = (RECT *)lp;
315             RECT16 rect16;
316
317             rect16.left   = rect32->left;
318             rect16.top    = rect32->top;
319             rect16.right  = rect32->right;
320             rect16.bottom = rect32->bottom;
321             lp = MapLS( &rect16 );
322             ret = call_hook_16( WH_CBT, code, wp, lp );
323             UnMapLS( lp );
324             break;
325         }
326     }
327     return ret;
328 }
329
330
331 /***********************************************************************
332  *              call_WH_MOUSE
333  */
334 static LRESULT CALLBACK call_WH_MOUSE( INT code, WPARAM wp, LPARAM lp )
335 {
336     MOUSEHOOKSTRUCT *ms32 = (MOUSEHOOKSTRUCT *)lp;
337     MOUSEHOOKSTRUCT16 ms16;
338     LRESULT ret;
339
340     ms16.pt.x         = ms32->pt.x;
341     ms16.pt.y         = ms32->pt.y;
342     ms16.hwnd         = HWND_16( ms32->hwnd );
343     ms16.wHitTestCode = ms32->wHitTestCode;
344     ms16.dwExtraInfo  = ms32->dwExtraInfo;
345
346     lp = MapLS( &ms16 );
347     ret = call_hook_16( WH_MOUSE, code, wp, lp );
348     UnMapLS( lp );
349     return ret;
350 }
351
352
353 /***********************************************************************
354  *              call_WH_SHELL
355  */
356 static LRESULT CALLBACK call_WH_SHELL( INT code, WPARAM wp, LPARAM lp )
357 {
358     return call_hook_16( WH_SHELL, code, wp, lp );
359 }
360
361
362 /***********************************************************************
363  *              SetWindowsHook (USER.121)
364  */
365 FARPROC16 WINAPI SetWindowsHook16( INT16 id, HOOKPROC16 proc )
366 {
367     HINSTANCE16 hInst = FarGetOwner16( HIWORD(proc) );
368
369     /* WH_MSGFILTER is the only task-specific hook for SetWindowsHook() */
370     HTASK16 hTask = (id == WH_MSGFILTER) ? GetCurrentTask() : 0;
371
372     return (FARPROC16)SetWindowsHookEx16( id, proc, hInst, hTask );
373 }
374
375
376 /***********************************************************************
377  *              SetWindowsHookEx (USER.291)
378  */
379 HHOOK WINAPI SetWindowsHookEx16( INT16 id, HOOKPROC16 proc, HINSTANCE16 hInst, HTASK16 hTask )
380 {
381     struct user_thread_info *thread_info = get_user_thread_info();
382     struct hook16_queue_info *info;
383     HHOOK hook;
384     int index = id - WH_MINHOOK;
385
386     if (id < WH_MINHOOK || id > WH_MAXHOOK16) return 0;
387     if (!hook_procs[index])
388     {
389         FIXME( "hook type %d broken in Win16\n", id );
390         return 0;
391     }
392     if (!hTask) FIXME( "System-global hooks (%d) broken in Win16\n", id );
393     else if (hTask != GetCurrentTask())
394     {
395         FIXME( "setting hook (%d) on other task not supported\n", id );
396         return 0;
397     }
398
399     if (!(info = thread_info->hook16_info))
400     {
401         if (!(info = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*info) ))) return 0;
402         thread_info->hook16_info = info;
403     }
404     if (info->hook[index])
405     {
406         FIXME( "Multiple hooks (%d) for the same task not supported yet\n", id );
407         return 0;
408     }
409     if (!(hook = SetWindowsHookExA( id, hook_procs[index], 0, GetCurrentThreadId() ))) return 0;
410     info->hook[index] = hook;
411     info->proc[index] = proc;
412     return hook;
413 }
414
415
416 /***********************************************************************
417  *              UnhookWindowsHook (USER.234)
418  */
419 BOOL16 WINAPI UnhookWindowsHook16( INT16 id, HOOKPROC16 proc )
420 {
421     struct hook16_queue_info *info;
422     int index = id - WH_MINHOOK;
423
424     if (id < WH_MINHOOK || id > WH_MAXHOOK16) return FALSE;
425     if (!(info = get_user_thread_info()->hook16_info)) return FALSE;
426     if (info->proc[index] != proc) return FALSE;
427     if (!UnhookWindowsHookEx( info->hook[index] )) return FALSE;
428     info->hook[index] = 0;
429     info->proc[index] = 0;
430     return TRUE;
431 }
432
433
434 /***********************************************************************
435  *              UnhookWindowsHookEx (USER.292)
436  */
437 BOOL16 WINAPI UnhookWindowsHookEx16( HHOOK hhook )
438 {
439     struct hook16_queue_info *info;
440     int index;
441
442     if (!(info = get_user_thread_info()->hook16_info)) return FALSE;
443     for (index = 0; index < NB_HOOKS16; index++)
444     {
445         if (info->hook[index] == hhook)
446         {
447             info->hook[index] = 0;
448             info->proc[index] = 0;
449             return UnhookWindowsHookEx( hhook );
450         }
451     }
452     return FALSE;
453 }
454
455
456 /***********************************************************************
457  *              CallMsgFilter32 (USER.823)
458  */
459 BOOL16 WINAPI CallMsgFilter32_16( MSG32_16 *lpmsg16_32, INT16 code, BOOL16 wHaveParamHigh )
460 {
461     MSG msg32;
462     BOOL16 ret;
463
464     if (GetSysModalWindow16()) return FALSE;
465     msg32.hwnd      = WIN_Handle32( lpmsg16_32->msg.hwnd );
466     msg32.message   = lpmsg16_32->msg.message;
467     msg32.lParam    = lpmsg16_32->msg.lParam;
468     msg32.time      = lpmsg16_32->msg.time;
469     msg32.pt.x      = lpmsg16_32->msg.pt.x;
470     msg32.pt.y      = lpmsg16_32->msg.pt.y;
471     if (wHaveParamHigh) msg32.wParam = MAKELONG(lpmsg16_32->msg.wParam, lpmsg16_32->wParamHigh);
472     else msg32.wParam = lpmsg16_32->msg.wParam;
473
474     ret = (BOOL16)CallMsgFilterA(&msg32, code);
475
476     lpmsg16_32->msg.hwnd    = HWND_16( msg32.hwnd );
477     lpmsg16_32->msg.message = msg32.message;
478     lpmsg16_32->msg.wParam  = LOWORD(msg32.wParam);
479     lpmsg16_32->msg.lParam  = msg32.lParam;
480     lpmsg16_32->msg.time    = msg32.time;
481     lpmsg16_32->msg.pt.x    = msg32.pt.x;
482     lpmsg16_32->msg.pt.y    = msg32.pt.y;
483     if (wHaveParamHigh) lpmsg16_32->wParamHigh = HIWORD(msg32.wParam);
484     return ret;
485 }
486
487
488 /***********************************************************************
489  *              CallMsgFilter (USER.123)
490  */
491 BOOL16 WINAPI CallMsgFilter16( MSG16 *msg, INT16 code )
492 {
493     return CallMsgFilter32_16( (MSG32_16 *)msg, code, FALSE );
494 }
495
496
497 /***********************************************************************
498  *              CallNextHookEx (USER.293)
499  */
500 LRESULT WINAPI CallNextHookEx16( HHOOK hhook, INT16 code, WPARAM16 wparam, LPARAM lparam )
501 {
502     struct hook16_queue_info *info;
503     LRESULT ret = 0;
504
505     if (!(info = get_user_thread_info()->hook16_info)) return 0;
506
507     switch (info->id)
508     {
509     case WH_MSGFILTER:
510     {
511         MSG16 *msg16 = MapSL(lparam);
512         MSG msg32;
513
514         map_msg_16_to_32( msg16, &msg32 );
515         ret = CallNextHookEx( hhook, code, wparam, (LPARAM)&msg32 );
516         break;
517     }
518
519     case WH_GETMESSAGE:
520     {
521         MSG16 *msg16 = MapSL(lparam);
522         MSG msg32;
523
524         map_msg_16_to_32( msg16, &msg32 );
525         ret = CallNextHookEx( hhook, code, wparam, (LPARAM)&msg32 );
526         map_msg_32_to_16( &msg32, msg16 );
527         break;
528     }
529
530     case WH_CALLWNDPROC:
531     {
532         CWPSTRUCT16 *cwp16 = MapSL(lparam);
533         LRESULT result;
534         struct wndproc_hook_params params;
535
536         params.hhook  = hhook;
537         params.code   = code;
538         params.wparam = wparam;
539         ret = WINPROC_CallProc16To32A( wndproc_hook_callback, cwp16->hwnd, cwp16->message,
540                                        cwp16->wParam, cwp16->lParam, &result, &params );
541         break;
542     }
543
544     case WH_CBT:
545         switch (code)
546         {
547         case HCBT_CREATEWND:
548             {
549                 CBT_CREATEWNDA cbtcw32;
550                 CREATESTRUCTA cs32;
551                 CBT_CREATEWND16 *cbtcw16 = MapSL(lparam);
552                 CREATESTRUCT16 *cs16 = MapSL( (SEGPTR)cbtcw16->lpcs );
553
554                 cbtcw32.lpcs = &cs32;
555                 cbtcw32.hwndInsertAfter = WIN_Handle32( cbtcw16->hwndInsertAfter );
556
557                 cs32.lpCreateParams = (LPVOID)cs16->lpCreateParams;
558                 cs32.hInstance      = HINSTANCE_32(cs16->hInstance);
559                 cs32.hMenu          = HMENU_32(cs16->hMenu);
560                 cs32.hwndParent     = WIN_Handle32(cs16->hwndParent);
561                 cs32.cy             = cs16->cy;
562                 cs32.cx             = cs16->cx;
563                 cs32.y              = cs16->y;
564                 cs32.x              = cs16->x;
565                 cs32.style          = cs16->style;
566                 cs32.lpszName       = MapSL( cs16->lpszName );
567                 cs32.lpszClass      = MapSL( cs16->lpszClass );
568                 cs32.dwExStyle      = cs16->dwExStyle;
569
570                 ret = CallNextHookEx( hhook, code, wparam, (LPARAM)&cbtcw32 );
571                 cbtcw16->hwndInsertAfter = HWND_16( cbtcw32.hwndInsertAfter );
572                 break;
573             }
574         case HCBT_ACTIVATE:
575             {
576                 CBTACTIVATESTRUCT16 *cas16 = MapSL(lparam);
577                 CBTACTIVATESTRUCT cas32;
578                 cas32.fMouse = cas16->fMouse;
579                 cas32.hWndActive = WIN_Handle32(cas16->hWndActive);
580                 ret = CallNextHookEx( hhook, code, wparam, (LPARAM)&cas32 );
581                 break;
582             }
583         case HCBT_CLICKSKIPPED:
584             {
585                 MOUSEHOOKSTRUCT16 *ms16 = MapSL(lparam);
586                 MOUSEHOOKSTRUCT ms32;
587
588                 ms32.pt.x = ms16->pt.x;
589                 ms32.pt.y = ms16->pt.y;
590                 /* wHitTestCode may be negative, so convince compiler to do
591                    correct sign extension. Yay. :| */
592                 ms32.wHitTestCode = (INT)(INT16)ms16->wHitTestCode;
593                 ms32.dwExtraInfo = ms16->dwExtraInfo;
594                 ms32.hwnd = WIN_Handle32( ms16->hwnd );
595                 ret = CallNextHookEx( hhook, code, wparam, (LPARAM)&ms32 );
596                 break;
597             }
598         case HCBT_MOVESIZE:
599             {
600                 RECT16 *rect16 = MapSL(lparam);
601                 RECT rect32;
602
603                 rect32.left   = rect16->left;
604                 rect32.top    = rect16->top;
605                 rect32.right  = rect16->right;
606                 rect32.bottom = rect16->bottom;
607                 ret = CallNextHookEx( hhook, code, wparam, (LPARAM)&rect32 );
608                 break;
609             }
610         }
611         break;
612
613     case WH_MOUSE:
614     {
615         MOUSEHOOKSTRUCT16 *ms16 = MapSL(lparam);
616         MOUSEHOOKSTRUCT ms32;
617
618         ms32.pt.x = ms16->pt.x;
619         ms32.pt.y = ms16->pt.y;
620         /* wHitTestCode may be negative, so convince compiler to do
621            correct sign extension. Yay. :| */
622         ms32.wHitTestCode = (INT)((INT16)ms16->wHitTestCode);
623         ms32.dwExtraInfo = ms16->dwExtraInfo;
624         ms32.hwnd = WIN_Handle32(ms16->hwnd);
625         ret = CallNextHookEx( hhook, code, wparam, (LPARAM)&ms32 );
626         break;
627     }
628
629     case WH_SHELL:
630     case WH_KEYBOARD:
631         ret = CallNextHookEx( hhook, code, wparam, lparam );
632         break;
633
634     case WH_HARDWARE:
635     case WH_FOREGROUNDIDLE:
636     case WH_CALLWNDPROCRET:
637     case WH_SYSMSGFILTER:
638     case WH_JOURNALRECORD:
639     case WH_JOURNALPLAYBACK:
640     default:
641         FIXME("\t[%i] 16to32 translation unimplemented\n", info->id);
642         ret = CallNextHookEx( hhook, code, wparam, lparam );
643         break;
644     }
645     return ret;
646 }
647
648
649 /***********************************************************************
650  *              DefHookProc (USER.235)
651  */
652 LRESULT WINAPI DefHookProc16( INT16 code, WPARAM16 wparam, LPARAM lparam, HHOOK *hhook )
653 {
654     return CallNextHookEx16( *hhook, code, wparam, lparam );
655 }