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