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