msi: Add a stub for MsiGetLastErrorRecord.
[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 "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 inline static 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 inline static 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 /***********************************************************************
137  *              call_WH_MSGFILTER
138  */
139 static LRESULT CALLBACK call_WH_MSGFILTER( INT code, WPARAM wp, LPARAM lp )
140 {
141     MSG *msg32 = (MSG *)lp;
142     MSG16 msg16;
143     LRESULT ret;
144
145     map_msg_32_to_16( msg32, &msg16 );
146     lp = MapLS( &msg16 );
147     ret = call_hook_16( WH_MSGFILTER, code, wp, lp );
148     UnMapLS( lp );
149     return ret;
150 }
151
152
153 /***********************************************************************
154  *              call_WH_KEYBOARD
155  */
156 static LRESULT CALLBACK call_WH_KEYBOARD( INT code, WPARAM wp, LPARAM lp )
157 {
158     return call_hook_16( WH_KEYBOARD, code, wp, lp );
159 }
160
161
162 /***********************************************************************
163  *              call_WH_GETMESSAGE
164  */
165 static LRESULT CALLBACK call_WH_GETMESSAGE( INT code, WPARAM wp, LPARAM lp )
166 {
167     MSG *msg32 = (MSG *)lp;
168     MSG16 msg16;
169     LRESULT ret;
170
171     map_msg_32_to_16( msg32, &msg16 );
172
173     lp = MapLS( &msg16 );
174     ret = call_hook_16( WH_GETMESSAGE, code, wp, lp );
175     UnMapLS( lp );
176
177     map_msg_16_to_32( &msg16, msg32 );
178     return ret;
179 }
180
181
182 /***********************************************************************
183  *              call_WH_CALLWNDPROC
184  */
185 static LRESULT CALLBACK call_WH_CALLWNDPROC( INT code, WPARAM wp, LPARAM lp )
186 {
187     CWPSTRUCT *cwp32 = (CWPSTRUCT *)lp;
188     CWPSTRUCT16 cwp16;
189     MSGPARAM16 mp16;
190     LRESULT ret;
191
192     cwp16.hwnd   = HWND_16(cwp32->hwnd);
193     cwp16.lParam = cwp32->lParam;
194
195     WINPROC_MapMsg32ATo16( cwp32->hwnd, cwp32->message, cwp32->wParam,
196                            &cwp16.message, &cwp16.wParam, &cwp16.lParam );
197
198     lp = MapLS( &cwp16 );
199     ret = call_hook_16( WH_CALLWNDPROC, code, wp, lp );
200     UnMapLS( lp );
201
202     mp16.wParam  = cwp16.wParam;
203     mp16.lParam  = cwp16.lParam;
204     mp16.lResult = 0;
205     WINPROC_UnmapMsg32ATo16( cwp32->hwnd, cwp32->message, cwp32->wParam, cwp32->lParam, &mp16 );
206     return ret;
207 }
208
209
210 /***********************************************************************
211  *              call_WH_CBT
212  */
213 static LRESULT CALLBACK call_WH_CBT( INT code, WPARAM wp, LPARAM lp )
214 {
215     LRESULT ret = 0;
216
217     switch (code)
218     {
219     case HCBT_CREATEWND:
220         {
221             CBT_CREATEWNDA *cbtcw32 = (CBT_CREATEWNDA *)lp;
222             CBT_CREATEWND16 cbtcw16;
223             CREATESTRUCT16 cs16;
224
225             cs16.lpCreateParams = (SEGPTR)cbtcw32->lpcs->lpCreateParams;
226             cs16.hInstance      = HINSTANCE_16(cbtcw32->lpcs->hInstance);
227             cs16.hMenu          = HMENU_16(cbtcw32->lpcs->hMenu);
228             cs16.hwndParent     = HWND_16(cbtcw32->lpcs->hwndParent);
229             cs16.cy             = cbtcw32->lpcs->cy;
230             cs16.cx             = cbtcw32->lpcs->cx;
231             cs16.y              = cbtcw32->lpcs->y;
232             cs16.x              = cbtcw32->lpcs->x;
233             cs16.style          = cbtcw32->lpcs->style;
234             cs16.lpszName       = MapLS( cbtcw32->lpcs->lpszName );
235             cs16.lpszClass      = MapLS( cbtcw32->lpcs->lpszClass );
236             cs16.dwExStyle      = cbtcw32->lpcs->dwExStyle;
237
238             cbtcw16.lpcs = (CREATESTRUCT16 *)MapLS( &cs16 );
239             cbtcw16.hwndInsertAfter = HWND_16( cbtcw32->hwndInsertAfter );
240
241             lp = MapLS( &cbtcw16 );
242             ret = call_hook_16( WH_CBT, code, wp, lp );
243             UnMapLS( cs16.lpszName );
244             UnMapLS( cs16.lpszClass );
245
246             cbtcw32->hwndInsertAfter = WIN_Handle32( cbtcw16.hwndInsertAfter );
247             UnMapLS( (SEGPTR)cbtcw16.lpcs );
248             UnMapLS( lp );
249             break;
250         }
251
252     case HCBT_ACTIVATE:
253         {
254             CBTACTIVATESTRUCT *cas32 = (CBTACTIVATESTRUCT *)lp;
255             CBTACTIVATESTRUCT16 cas16;
256
257             cas16.fMouse     = cas32->fMouse;
258             cas16.hWndActive = HWND_16( cas32->hWndActive );
259
260             lp = MapLS( &cas16 );
261             ret = call_hook_16( WH_CBT, code, wp, lp );
262             UnMapLS( lp );
263             break;
264         }
265     case HCBT_CLICKSKIPPED:
266         {
267             MOUSEHOOKSTRUCT *ms32 = (MOUSEHOOKSTRUCT *)lp;
268             MOUSEHOOKSTRUCT16 ms16;
269
270             ms16.pt.x         = ms32->pt.x;
271             ms16.pt.y         = ms32->pt.y;
272             ms16.hwnd         = HWND_16( ms32->hwnd );
273             ms16.wHitTestCode = ms32->wHitTestCode;
274             ms16.dwExtraInfo  = ms32->dwExtraInfo;
275
276             lp = MapLS( &ms16 );
277             ret = call_hook_16( WH_CBT, code, wp, lp );
278             UnMapLS( lp );
279             break;
280         }
281     case HCBT_MOVESIZE:
282         {
283             RECT *rect32 = (RECT *)lp;
284             RECT16 rect16;
285
286             rect16.left   = rect32->left;
287             rect16.top    = rect32->top;
288             rect16.right  = rect32->right;
289             rect16.bottom = rect32->bottom;
290             lp = MapLS( &rect16 );
291             ret = call_hook_16( WH_CBT, code, wp, lp );
292             UnMapLS( lp );
293             break;
294         }
295     }
296     return ret;
297 }
298
299
300 /***********************************************************************
301  *              call_WH_MOUSE
302  */
303 static LRESULT CALLBACK call_WH_MOUSE( INT code, WPARAM wp, LPARAM lp )
304 {
305     MOUSEHOOKSTRUCT *ms32 = (MOUSEHOOKSTRUCT *)lp;
306     MOUSEHOOKSTRUCT16 ms16;
307     LRESULT ret;
308
309     ms16.pt.x         = ms32->pt.x;
310     ms16.pt.y         = ms32->pt.y;
311     ms16.hwnd         = HWND_16( ms32->hwnd );
312     ms16.wHitTestCode = ms32->wHitTestCode;
313     ms16.dwExtraInfo  = ms32->dwExtraInfo;
314
315     lp = MapLS( &ms16 );
316     ret = call_hook_16( WH_MOUSE, code, wp, lp );
317     UnMapLS( lp );
318     return ret;
319 }
320
321
322 /***********************************************************************
323  *              call_WH_SHELL
324  */
325 static LRESULT CALLBACK call_WH_SHELL( INT code, WPARAM wp, LPARAM lp )
326 {
327     return call_hook_16( WH_SHELL, code, wp, lp );
328 }
329
330
331 /***********************************************************************
332  *              SetWindowsHook (USER.121)
333  */
334 FARPROC16 WINAPI SetWindowsHook16( INT16 id, HOOKPROC16 proc )
335 {
336     HINSTANCE16 hInst = FarGetOwner16( HIWORD(proc) );
337
338     /* WH_MSGFILTER is the only task-specific hook for SetWindowsHook() */
339     HTASK16 hTask = (id == WH_MSGFILTER) ? GetCurrentTask() : 0;
340
341     return (FARPROC16)SetWindowsHookEx16( id, proc, hInst, hTask );
342 }
343
344
345 /***********************************************************************
346  *              SetWindowsHookEx (USER.291)
347  */
348 HHOOK WINAPI SetWindowsHookEx16( INT16 id, HOOKPROC16 proc, HINSTANCE16 hInst, HTASK16 hTask )
349 {
350     struct user_thread_info *thread_info = get_user_thread_info();
351     struct hook16_queue_info *info;
352     HHOOK hook;
353     int index = id - WH_MINHOOK;
354
355     if (id < WH_MINHOOK || id > WH_MAXHOOK16) return 0;
356     if (!hook_procs[index])
357     {
358         FIXME( "hook type %d broken in Win16\n", id );
359         return 0;
360     }
361     if (!hTask) FIXME( "System-global hooks (%d) broken in Win16\n", id );
362     else if (hTask != GetCurrentTask())
363     {
364         FIXME( "setting hook (%d) on other task not supported\n", id );
365         return 0;
366     }
367
368     if (!(info = thread_info->hook16_info))
369     {
370         if (!(info = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*info) ))) return 0;
371         thread_info->hook16_info = info;
372     }
373     if (info->hook[index])
374     {
375         FIXME( "Multiple hooks (%d) for the same task not supported yet\n", id );
376         return 0;
377     }
378     if (!(hook = SetWindowsHookExA( id, hook_procs[index], 0, GetCurrentThreadId() ))) return 0;
379     info->hook[index] = hook;
380     info->proc[index] = proc;
381     return hook;
382 }
383
384
385 /***********************************************************************
386  *              UnhookWindowsHook (USER.234)
387  */
388 BOOL16 WINAPI UnhookWindowsHook16( INT16 id, HOOKPROC16 proc )
389 {
390     struct hook16_queue_info *info;
391     int index = id - WH_MINHOOK;
392
393     if (id < WH_MINHOOK || id > WH_MAXHOOK16) return FALSE;
394     if (!(info = get_user_thread_info()->hook16_info)) return FALSE;
395     if (info->proc[index] != proc) return FALSE;
396     if (!UnhookWindowsHookEx( info->hook[index] )) return FALSE;
397     info->hook[index] = 0;
398     info->proc[index] = 0;
399     return TRUE;
400 }
401
402
403 /***********************************************************************
404  *              UnhookWindowsHookEx (USER.292)
405  */
406 BOOL16 WINAPI UnhookWindowsHookEx16( HHOOK hhook )
407 {
408     struct hook16_queue_info *info;
409     int index;
410
411     if (!(info = get_user_thread_info()->hook16_info)) return FALSE;
412     for (index = 0; index < NB_HOOKS16; index++)
413     {
414         if (info->hook[index] == hhook)
415         {
416             info->hook[index] = 0;
417             info->proc[index] = 0;
418             return UnhookWindowsHookEx( hhook );
419         }
420     }
421     return FALSE;
422 }
423
424
425 /***********************************************************************
426  *              CallMsgFilter32 (USER.823)
427  */
428 BOOL16 WINAPI CallMsgFilter32_16( MSG32_16 *lpmsg16_32, INT16 code, BOOL16 wHaveParamHigh )
429 {
430     MSG msg32;
431     BOOL16 ret;
432
433     if (GetSysModalWindow16()) return FALSE;
434     msg32.hwnd      = WIN_Handle32( lpmsg16_32->msg.hwnd );
435     msg32.message   = lpmsg16_32->msg.message;
436     msg32.lParam    = lpmsg16_32->msg.lParam;
437     msg32.time      = lpmsg16_32->msg.time;
438     msg32.pt.x      = lpmsg16_32->msg.pt.x;
439     msg32.pt.y      = lpmsg16_32->msg.pt.y;
440     if (wHaveParamHigh) msg32.wParam = MAKELONG(lpmsg16_32->msg.wParam, lpmsg16_32->wParamHigh);
441     else msg32.wParam = lpmsg16_32->msg.wParam;
442
443     ret = (BOOL16)CallMsgFilterA(&msg32, code);
444
445     lpmsg16_32->msg.hwnd    = HWND_16( msg32.hwnd );
446     lpmsg16_32->msg.message = msg32.message;
447     lpmsg16_32->msg.wParam  = LOWORD(msg32.wParam);
448     lpmsg16_32->msg.lParam  = msg32.lParam;
449     lpmsg16_32->msg.time    = msg32.time;
450     lpmsg16_32->msg.pt.x    = msg32.pt.x;
451     lpmsg16_32->msg.pt.y    = msg32.pt.y;
452     if (wHaveParamHigh) lpmsg16_32->wParamHigh = HIWORD(msg32.wParam);
453     return ret;
454 }
455
456
457 /***********************************************************************
458  *              CallMsgFilter (USER.123)
459  */
460 BOOL16 WINAPI CallMsgFilter16( MSG16 *msg, INT16 code )
461 {
462     return CallMsgFilter32_16( (MSG32_16 *)msg, code, FALSE );
463 }
464
465
466 /***********************************************************************
467  *              CallNextHookEx (USER.293)
468  */
469 LRESULT WINAPI CallNextHookEx16( HHOOK hhook, INT16 code, WPARAM16 wparam, LPARAM lparam )
470 {
471     struct hook16_queue_info *info;
472     LRESULT ret = 0;
473
474     if (!(info = get_user_thread_info()->hook16_info)) return 0;
475
476     switch (info->id)
477     {
478     case WH_MSGFILTER:
479     {
480         MSG16 *msg16 = MapSL(lparam);
481         MSG msg32;
482
483         map_msg_16_to_32( msg16, &msg32 );
484         ret = CallNextHookEx( hhook, code, wparam, (LPARAM)&msg32 );
485         break;
486     }
487
488     case WH_GETMESSAGE:
489     {
490         MSG16 *msg16 = MapSL(lparam);
491         MSG msg32;
492
493         map_msg_16_to_32( msg16, &msg32 );
494         ret = CallNextHookEx( hhook, code, wparam, (LPARAM)&msg32 );
495         map_msg_32_to_16( &msg32, msg16 );
496         break;
497     }
498
499     case WH_CALLWNDPROC:
500     {
501         CWPSTRUCT16 *cwp16 = MapSL(lparam);
502         CWPSTRUCT cwp32;
503
504         cwp32.hwnd   = WIN_Handle32(cwp16->hwnd);
505         cwp32.lParam = cwp16->lParam;
506
507         WINPROC_MapMsg16To32A( cwp32.hwnd, cwp16->message, cwp16->wParam,
508                                &cwp32.message, &cwp32.wParam, &cwp32.lParam );
509         ret = CallNextHookEx( hhook, code, wparam, (LPARAM)&cwp32 );
510         WINPROC_UnmapMsg16To32A( cwp32.hwnd, cwp32.message, cwp32.wParam, cwp32.lParam, 0 );
511         break;
512     }
513
514     case WH_CBT:
515         switch (code)
516         {
517         case HCBT_CREATEWND:
518             {
519                 CBT_CREATEWNDA cbtcw32;
520                 CREATESTRUCTA cs32;
521                 CBT_CREATEWND16 *cbtcw16 = MapSL(lparam);
522                 CREATESTRUCT16 *cs16 = MapSL( (SEGPTR)cbtcw16->lpcs );
523
524                 cbtcw32.lpcs = &cs32;
525                 cbtcw32.hwndInsertAfter = WIN_Handle32( cbtcw16->hwndInsertAfter );
526
527                 cs32.lpCreateParams = (LPVOID)cs16->lpCreateParams;
528                 cs32.hInstance      = HINSTANCE_32(cs16->hInstance);
529                 cs32.hMenu          = HMENU_32(cs16->hMenu);
530                 cs32.hwndParent     = WIN_Handle32(cs16->hwndParent);
531                 cs32.cy             = cs16->cy;
532                 cs32.cx             = cs16->cx;
533                 cs32.y              = cs16->y;
534                 cs32.x              = cs16->x;
535                 cs32.style          = cs16->style;
536                 cs32.lpszName       = MapSL( cs16->lpszName );
537                 cs32.lpszClass      = MapSL( cs16->lpszClass );
538                 cs32.dwExStyle      = cs16->dwExStyle;
539
540                 ret = CallNextHookEx( hhook, code, wparam, (LPARAM)&cbtcw32 );
541                 cbtcw16->hwndInsertAfter = HWND_16( cbtcw32.hwndInsertAfter );
542                 break;
543             }
544         case HCBT_ACTIVATE:
545             {
546                 CBTACTIVATESTRUCT16 *cas16 = MapSL(lparam);
547                 CBTACTIVATESTRUCT cas32;
548                 cas32.fMouse = cas16->fMouse;
549                 cas32.hWndActive = WIN_Handle32(cas16->hWndActive);
550                 ret = CallNextHookEx( hhook, code, wparam, (LPARAM)&cas32 );
551                 break;
552             }
553         case HCBT_CLICKSKIPPED:
554             {
555                 MOUSEHOOKSTRUCT16 *ms16 = MapSL(lparam);
556                 MOUSEHOOKSTRUCT ms32;
557
558                 ms32.pt.x = ms16->pt.x;
559                 ms32.pt.y = ms16->pt.y;
560                 /* wHitTestCode may be negative, so convince compiler to do
561                    correct sign extension. Yay. :| */
562                 ms32.wHitTestCode = (INT)(INT16)ms16->wHitTestCode;
563                 ms32.dwExtraInfo = ms16->dwExtraInfo;
564                 ms32.hwnd = WIN_Handle32( ms16->hwnd );
565                 ret = CallNextHookEx( hhook, code, wparam, (LPARAM)&ms32 );
566                 break;
567             }
568         case HCBT_MOVESIZE:
569             {
570                 RECT16 *rect16 = MapSL(lparam);
571                 RECT rect32;
572
573                 rect32.left   = rect16->left;
574                 rect32.top    = rect16->top;
575                 rect32.right  = rect16->right;
576                 rect32.bottom = rect16->bottom;
577                 ret = CallNextHookEx( hhook, code, wparam, (LPARAM)&rect32 );
578                 break;
579             }
580         }
581         break;
582
583     case WH_MOUSE:
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
599     case WH_SHELL:
600     case WH_KEYBOARD:
601         ret = CallNextHookEx( hhook, code, wparam, lparam );
602         break;
603
604     case WH_HARDWARE:
605     case WH_FOREGROUNDIDLE:
606     case WH_CALLWNDPROCRET:
607     case WH_SYSMSGFILTER:
608     case WH_JOURNALRECORD:
609     case WH_JOURNALPLAYBACK:
610     default:
611         FIXME("\t[%i] 16to32 translation unimplemented\n", info->id);
612         ret = CallNextHookEx( hhook, code, wparam, lparam );
613         break;
614     }
615     return ret;
616 }
617
618
619 /***********************************************************************
620  *              DefHookProc (USER.235)
621  */
622 LRESULT WINAPI DefHookProc16( INT16 code, WPARAM16 wparam, LPARAM lparam, HHOOK *hhook )
623 {
624     return CallNextHookEx16( *hhook, code, wparam, lparam );
625 }