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